diff --git a/previews/PR655/.documenter-siteinfo.json b/previews/PR655/.documenter-siteinfo.json index 28295ae373..80fac5a587 100644 --- a/previews/PR655/.documenter-siteinfo.json +++ b/previews/PR655/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.6.7","generation_timestamp":"2024-03-20T19:29:12","documenter_version":"1.3.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-03-20T20:48:14","documenter_version":"1.3.0"}} \ No newline at end of file diff --git a/previews/PR655/Getting_Started/commercial_solvers/index.html b/previews/PR655/Getting_Started/commercial_solvers/index.html index d4ff247b27..9376e9573e 100644 --- a/previews/PR655/Getting_Started/commercial_solvers/index.html +++ b/previews/PR655/Getting_Started/commercial_solvers/index.html @@ -7,4 +7,4 @@ (GenX) pkg> add CPLEX
using Gurobi
 using GenX
 
-run_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)
Warning

Note that if you have not already installed the required Julia packages or you do not have a valid Gurobi license on your host machine, you will receive an error message and Run.jl will not run to completion.

+run_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)
Warning

Note that if you have not already installed the required Julia packages or you do not have a valid Gurobi license on your host machine, you will receive an error message and Run.jl will not run to completion.

diff --git a/previews/PR655/Getting_Started/examples_casestudies/index.html b/previews/PR655/Getting_Started/examples_casestudies/index.html index 65204c00eb..8137c64ceb 100644 --- a/previews/PR655/Getting_Started/examples_casestudies/index.html +++ b/previews/PR655/Getting_Started/examples_casestudies/index.html @@ -43,4 +43,4 @@ using Gurobi run_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)

To run the case, open a terminal and run the following command:

$ julia --project="/path/to/env"
-julia> include("/path/to/MyCase/Run.jl")

where /path/to/env is the path to the environment with GenX installed, and /path/to/MyCase is the path to the folder of the MyCase case. Alternatively, you can run the case directly from the terminal using the following command:

$ julia --project="/path/to/env" /path/to/MyCase/Run.jl

What happens when you run a case

Added in 0.3.4

The entry point for running a GenX case is the run_genx_case!("path/to/case") function, where path/to/case is the path to the case directory that contains the .csv files with the inputs for GenX and the settings folder with the configuration files.

The following are the main steps performed in this function:

  1. Establish path to environment setup files and GenX source files.
  2. Read in model settings genx_settings.yml from the example directory.
  3. Configure solver settings.
  4. Load the model inputs from the example directory and perform time-domain clustering if required.
  5. Generate a GenX model instance.
  6. Solve the model.
  7. Write the output files to a specified directory.

After the script runs to completion, results will be written to a folder called results, located in the current working directory.

+julia> include("/path/to/MyCase/Run.jl")

where /path/to/env is the path to the environment with GenX installed, and /path/to/MyCase is the path to the folder of the MyCase case. Alternatively, you can run the case directly from the terminal using the following command:

$ julia --project="/path/to/env" /path/to/MyCase/Run.jl

What happens when you run a case

Added in 0.3.4

The entry point for running a GenX case is the run_genx_case!("path/to/case") function, where path/to/case is the path to the case directory that contains the .csv files with the inputs for GenX and the settings folder with the configuration files.

The following are the main steps performed in this function:

  1. Establish path to environment setup files and GenX source files.
  2. Read in model settings genx_settings.yml from the example directory.
  3. Configure solver settings.
  4. Load the model inputs from the example directory and perform time-domain clustering if required.
  5. Generate a GenX model instance.
  6. Solve the model.
  7. Write the output files to a specified directory.

After the script runs to completion, results will be written to a folder called results, located in the current working directory.

diff --git a/previews/PR655/Model_Concept_Overview/model_introduction/index.html b/previews/PR655/Model_Concept_Overview/model_introduction/index.html index e8bd9c6598..f7efec4c91 100644 --- a/previews/PR655/Model_Concept_Overview/model_introduction/index.html +++ b/previews/PR655/Model_Concept_Overview/model_introduction/index.html @@ -1,2 +1,2 @@ -Model Introduction · GenX

GenX Model Introduction

Introduction

GenX allows for the simultaneous co-optimization of several interlinked power system decision layers, described below:

  1. Capacity expansion planning (e.g., investment and retirement decisions for a full range of centralized and distributed generation, storage, and demand-side resources)
  2. Hourly dispatch of generation, storage, and demand-side resources,
  3. Unit commitment decisions and operational constraints for thermal generators,
  4. Commitment of generation, storage, and demand-side capacity to meet system operating reserves requirements,
  5. Commitment of generation, storage, and demand-side capacity to meet capacity reserve requirements,
  6. Transmission network power flows (including losses) and network expansion decisions, and
  7. Several optional policy constraints

Depending on the dimensionality of the problem, it may not be possible to model all decision layers at the highest possible resolution of detail, so the GenX model is designed to be highly configurable, allowing the user to specify the level of detail or abstraction along each of these layers or to omit one or more layers from consideration entirely.

For example, while investment and dispatch decisions (Layers 1 and 2) are a consistent feature of the model under all configurations, the user has several options with regards to representing the operational constraints on various thermal power plants (e.g., coal, gas, nuclear, and biomass generators). Unit commitment (e.g., start-up and shut-down) decisions Morales-España et al., 2013 (Layer 3) can be modeled at the individual power plant level (as per De Sisternes Jimenez, 2014); by using an efficient clustering of similar or identical units (as per Palmintier, 2011, Palmintier, 2013, Palmintier, 2014); by using a linear relaxation (or convex hull) of the integer unit commitment constraints set; or ignoring unit commitment decisions entirely and treating generator output as fully continuous. Furthermore, different levels of resolution can be selected for each individual resource type, as desired (e.g., larger thermal units can be represented with integer unit commitment decisions while smaller units can be treated as fully continuous). In such a manner, the model can be configured to represent operating constraints on thermal generators at a level of resolution that achieves a desired balance between abstraction error and computational tractability and provides sufficient accuracy to generate insights for the problem at hand.

The model can also be configured to consider commitment of capacity to supply frequency regulation (symmetric up and down) and operating reserves (up) needed by system operators to robustly resolve short-term uncertainty in demand and renewable energy forecasts and power plant or transmission network failures (Layer 4). Alternatively, reserve commitments can be ignored if desired.

Additionally, the model can approximate resource adequacy requirements through capacity reserve margin requirements at the zonal and/or system level (Layer 5). In this way, the model can approximate varying structure of capacity markets seen in deregulated electricity markets in the U.S. and other regions.

The model also allows for transmission networks to be represented at several levels of detail (Layer 6) including at a zonal level with transport constraints on power flows between zones (as per Mai et al., 2013, Johnston et al., 2013, Hirth, 2017); or as a single zone problem where transmission constraints and flows are ignored. (A DC optimal power flow formulation is in development.) In cases where a nodal or zonal transmission model is employed, network capacity expansion decisions can be modeled or ignored, and transmission losses can be represented either as a linear function of power flows or a piecewise linear approximation of a quadratic function of power flows between nodes or zones (as per Zhang et al., 2013, Fitiwi et al., 2016), with the number of segments in the piecewise approximation specified by the user as desired. In a multi-zonal or nodal configuration, GenX can therefore consider siting generators in different locations, including balancing tradeoffs between access to different renewable resource quality, siting restrictions, and impacts on network congestions, power flows and losses.

GenX also allows the user to specify several optional public policy constraints, such as CO2 emissions limits, minimum energy share requirements (such as renewable portfolio standard or clean energy standard policies), and minimum technology capacity requirements (e.g. technology deployment mandates).

Finally, the model is usually configured to consider a full year of operating decisions at an hourly resolution, but as this is often not tractable when considering large-scale problems with high resolution in other dimensions, GenX is also designed to model a number of subperiods – typically multiday periods of chronologically sequential hourly operating decisions – that can be selected via appropriate statistical clustering methods to represent a full year of operations (De Sisternes Jimenez and Webster, 2013, De Sisternes Jimenez, 2014, Poncelet et al., 2016, Nahmmacher et al., 2016, Blanford et al., 2016, Merrick, 2016, Mallapragada et al., 2018). GenX ships with a built-in time-domain reduction package that uses k-means or k-medoids to cluster raw time series data for demand (load) profiles and resource capacity factor profiles into representative periods during the input processing stage of the model. This method can also consider extreme points in the time series to capture noteworthy periods or periods with notably poor fits.

With appropriate configuration of the model, GenX thus allows the user to tractably consider several interlinking decision layers in a single, monolithic optimization problem that would otherwise have been necessary to solve in different separated stages or models. The following figure reflects the range of configurations currently possible along the three key dimensions of chronological detail, operational detail, and network detail.

Range of configurations currently implemented in GenX along three key dimensions of model resolution Figure. Range of configurations currently implemented in GenX along three key dimensions of model resolution

The model can be configured to consider a single future planning year or multiple planning stages (or investment periods) in sequence.

  • In single-stage planning mode, the model formulation is static, in the sense that its objective is not to determine when investments should take place over time, but rather to produce a snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions.
  • The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here.
  • The user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as "myopic" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.

More information on the two sequential, multi-stage planning modes can be found in the section on Multi-stage under the Model function reference tab.

Uses

From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.

+Model Introduction · GenX

GenX Model Introduction

Introduction

GenX allows for the simultaneous co-optimization of several interlinked power system decision layers, described below:

  1. Capacity expansion planning (e.g., investment and retirement decisions for a full range of centralized and distributed generation, storage, and demand-side resources)
  2. Hourly dispatch of generation, storage, and demand-side resources,
  3. Unit commitment decisions and operational constraints for thermal generators,
  4. Commitment of generation, storage, and demand-side capacity to meet system operating reserves requirements,
  5. Commitment of generation, storage, and demand-side capacity to meet capacity reserve requirements,
  6. Transmission network power flows (including losses) and network expansion decisions, and
  7. Several optional policy constraints

Depending on the dimensionality of the problem, it may not be possible to model all decision layers at the highest possible resolution of detail, so the GenX model is designed to be highly configurable, allowing the user to specify the level of detail or abstraction along each of these layers or to omit one or more layers from consideration entirely.

For example, while investment and dispatch decisions (Layers 1 and 2) are a consistent feature of the model under all configurations, the user has several options with regards to representing the operational constraints on various thermal power plants (e.g., coal, gas, nuclear, and biomass generators). Unit commitment (e.g., start-up and shut-down) decisions Morales-España et al., 2013 (Layer 3) can be modeled at the individual power plant level (as per De Sisternes Jimenez, 2014); by using an efficient clustering of similar or identical units (as per Palmintier, 2011, Palmintier, 2013, Palmintier, 2014); by using a linear relaxation (or convex hull) of the integer unit commitment constraints set; or ignoring unit commitment decisions entirely and treating generator output as fully continuous. Furthermore, different levels of resolution can be selected for each individual resource type, as desired (e.g., larger thermal units can be represented with integer unit commitment decisions while smaller units can be treated as fully continuous). In such a manner, the model can be configured to represent operating constraints on thermal generators at a level of resolution that achieves a desired balance between abstraction error and computational tractability and provides sufficient accuracy to generate insights for the problem at hand.

The model can also be configured to consider commitment of capacity to supply frequency regulation (symmetric up and down) and operating reserves (up) needed by system operators to robustly resolve short-term uncertainty in demand and renewable energy forecasts and power plant or transmission network failures (Layer 4). Alternatively, reserve commitments can be ignored if desired.

Additionally, the model can approximate resource adequacy requirements through capacity reserve margin requirements at the zonal and/or system level (Layer 5). In this way, the model can approximate varying structure of capacity markets seen in deregulated electricity markets in the U.S. and other regions.

The model also allows for transmission networks to be represented at several levels of detail (Layer 6) including at a zonal level with transport constraints on power flows between zones (as per Mai et al., 2013, Johnston et al., 2013, Hirth, 2017); or as a single zone problem where transmission constraints and flows are ignored. (A DC optimal power flow formulation is in development.) In cases where a nodal or zonal transmission model is employed, network capacity expansion decisions can be modeled or ignored, and transmission losses can be represented either as a linear function of power flows or a piecewise linear approximation of a quadratic function of power flows between nodes or zones (as per Zhang et al., 2013, Fitiwi et al., 2016), with the number of segments in the piecewise approximation specified by the user as desired. In a multi-zonal or nodal configuration, GenX can therefore consider siting generators in different locations, including balancing tradeoffs between access to different renewable resource quality, siting restrictions, and impacts on network congestions, power flows and losses.

GenX also allows the user to specify several optional public policy constraints, such as CO2 emissions limits, minimum energy share requirements (such as renewable portfolio standard or clean energy standard policies), and minimum technology capacity requirements (e.g. technology deployment mandates).

Finally, the model is usually configured to consider a full year of operating decisions at an hourly resolution, but as this is often not tractable when considering large-scale problems with high resolution in other dimensions, GenX is also designed to model a number of subperiods – typically multiday periods of chronologically sequential hourly operating decisions – that can be selected via appropriate statistical clustering methods to represent a full year of operations (De Sisternes Jimenez and Webster, 2013, De Sisternes Jimenez, 2014, Poncelet et al., 2016, Nahmmacher et al., 2016, Blanford et al., 2016, Merrick, 2016, Mallapragada et al., 2018). GenX ships with a built-in time-domain reduction package that uses k-means or k-medoids to cluster raw time series data for demand (load) profiles and resource capacity factor profiles into representative periods during the input processing stage of the model. This method can also consider extreme points in the time series to capture noteworthy periods or periods with notably poor fits.

With appropriate configuration of the model, GenX thus allows the user to tractably consider several interlinking decision layers in a single, monolithic optimization problem that would otherwise have been necessary to solve in different separated stages or models. The following figure reflects the range of configurations currently possible along the three key dimensions of chronological detail, operational detail, and network detail.

Range of configurations currently implemented in GenX along three key dimensions of model resolution Figure. Range of configurations currently implemented in GenX along three key dimensions of model resolution

The model can be configured to consider a single future planning year or multiple planning stages (or investment periods) in sequence.

  • In single-stage planning mode, the model formulation is static, in the sense that its objective is not to determine when investments should take place over time, but rather to produce a snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions.
  • The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here.
  • The user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as "myopic" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.

More information on the two sequential, multi-stage planning modes can be found in the section on Multi-stage under the Model function reference tab.

Uses

From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.

diff --git a/previews/PR655/Model_Concept_Overview/model_notation/index.html b/previews/PR655/Model_Concept_Overview/model_notation/index.html index 677c5c5786..5b621b52e0 100644 --- a/previews/PR655/Model_Concept_Overview/model_notation/index.html +++ b/previews/PR655/Model_Concept_Overview/model_notation/index.html @@ -1,2 +1,2 @@ -Notation · GenX

Model Notation

Model Indices and Sets


NotationDescription
$t \in \mathcal{T}$where $t$ denotes an time step and $\mathcal{T}$ is the set of time steps over which grid operations are modeled
$\mathcal{T}^{interior} \subseteq \mathcal{T}^{}$where $\mathcal{T}^{interior}$ is the set of interior timesteps in the data series
$\mathcal{T}^{start} \subseteq \mathcal{T}$where $\mathcal{T}^{start}$ is the set of initial timesteps in the data series. $\mathcal{T}^{start}={1}$ when representing entire year as a single contiguous period; $\mathcal{T}^{start}=\{\left(m-1\right) \times \tau^{period}+1 | m \in \mathcal{M}\}$, which corresponds to the first time step of each representative period $m \in \mathcal{M}$
$n \in \mathcal{N}$where $n$ corresponds to a contiguous time period and $\mathcal{N}$ corresponds to the set of contiguous periods of length $\tau^{period}$ that make up the input time series (e.g. demand, variable renewable energy availability) to the model
$\mathcal{N}^{rep} \subseteq \mathcal{N}$where $\mathcal{N}^{rep}$ corresponds to the set of representative time periods that are selected from the set of contiguous periods, $\mathcal{M}$
$m \in \mathcal{M}$where $m$ corresponds to a representative time period and $\mathcal{M}$ corresponds to the set of representative time periods indexed as per their chronological ocurrence in the set of contiguous periods spanning the input time series data, i.e. $\mathcal{N}$
$z \in \mathcal{Z}$where $z$ denotes a zone and $\mathcal{Z}$ is the set of zones in the network
$l \in \mathcal{L}$where $l$ denotes a line and $\mathcal{L}$ is the set of transmission lines in the network
$y \in \mathcal{G}$where $y$ denotes a technology and $\mathcal{G}$ is the set of available technologies
$\mathcal{H} \subseteq \mathcal{G}$where $\mathcal{H}$ is the subset of thermal resources
$\mathcal{VRE} \subseteq \mathcal{G}$where $\mathcal{VRE}$ is the subset of curtailable Variable Renewable Energy (VRE) resources
$\overline{\mathcal{VRE}}^{y,z}$set of VRE resource bins for VRE technology type $y \in \mathcal{VRE}$ in zone $z$
$\mathcal{CE} \subseteq \mathcal{G}$where $\mathcal{CE}$ is the subset of resources qualifying for the clean energy standard policy constraint
$\mathcal{UC} \subseteq \mathcal{H}$where $\mathcal{UC}$ is the subset of thermal resources subject to unit commitment constraints
$s \in \mathcal{S}$where $s$ denotes a segment and $\mathcal{S}$ is the set of consumers segments for price-responsive demand curtailment
$\mathcal{O} \subseteq \mathcal{G}$where $\mathcal{O}$ is the subset of storage resources excluding heat storage and hydro storage
$o \in \mathcal{O}$where $o$ denotes a storage technology in a set $\mathcal{O}$
$\mathcal{O}^{sym} \subseteq \mathcal{O}$where $\mathcal{O}^{sym}$ corresponds to the set of energy storage technologies with equal (or symmetric) charge and discharge power capacities
$\mathcal{O}^{asym} \subseteq \mathcal{O}$where $\mathcal{O}^{asym}$ corresponds to the set of energy storage technologies with independently sized (or asymmetric) charge and discharge power capacities
$\mathcal{O}^{LDES} \subseteq \mathcal{O}$where $\mathcal{O}^{LDES}$ corresponds to the set of long-duration energy storage technologies for which inter-period energy exchange is permitted when using representative periods to model annual grid operations
$\mathcal{VS} \subseteq \mathcal{G}$where $\mathcal{VS}$ is the subset of co-located VRE and storage resources
$\mathcal{VS}^{pv} \subseteq \mathcal{VS}$where $\mathcal{VS}^{pv}$ corresponds to the set of co-located VRE and storage resources with a solar PV component
$\mathcal{VS}^{wind} \subseteq \mathcal{VS}$where $\mathcal{VS}^{wind}$ corresponds to the set of co-located VRE and storage resources with a wind component
$\mathcal{VS}^{inv} \subseteq \mathcal{VS}$where $\mathcal{VS}^{inv}$ corresponds to the set of co-located VRE and storage resources with an inverter component
$\mathcal{VS}^{stor} \subseteq \mathcal{VS}$where $\mathcal{VS}^{stor}$ corresponds to the set of co-located VRE and storage resources with a storage component
$\mathcal{VS}^{sym, dc} \subseteq \mathcal{VS}$where $\mathcal{VS}^{sym, dc}$ corresponds to the set of co-located VRE and storage resources with a storage DC component with equal (or symmetric) charge and discharge power capacities
$\mathcal{VS}^{sym, ac} \subseteq \mathcal{VS}$where $\mathcal{VS}^{sym, ac}$ corresponds to the set of co-located VRE and storage resources with a storage AC component with equal (or symmetric) charge and discharge power capacities
$\mathcal{VS}^{asym, dc, dis} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, dc, dis}$ corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) discharge power capabilities
$\mathcal{VS}^{asym, dc, cha} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, dc, cha}$ corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) charge power capabilities
$\mathcal{VS}^{asym, ac, dis} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, ac, dis}$ corresponds to the set of co-located VRE and storage with a storage AC component with independently sized (or asymmetric) discharge power capabilities
$\mathcal{VS}^{asym, ac, cha} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, ac, cha}$ corresponds to the set of co-located VRE and storage resources with a storage AC component with independently sized (or asymmetric) charge power capabilities
$\mathcal{VS}^{LDES} \subseteq \mathcal{VS}$where $\mathcal{VS}^{LDES}$ corresponds to the set of co-located VRE and storage resources with a long-duration energy storage component for which inter-period energy exchange is permitted when using representative periods to model annual grid operations
$\mathcal{W} \subseteq \mathcal{G}$where $\mathcal{W}$ set of hydroelectric generators with water storage reservoirs
$\mathcal{W}^{nocap} \subseteq \mathcal{W}$where $\mathcal{W}^{nocap}$ is a subset of set of $ \mathcal{W}$ and represents resources with unknown reservoir capacity
$\mathcal{W}^{cap} \subseteq \mathcal{W}$where $\mathcal{W}^{cap}$ is a subset of set of $ \mathcal{W}$ and represents resources with known reservoir capacity
$\mathcal{MR} \subseteq \mathcal{G}$where $\mathcal{MR}$ set of must-run resources
$\mathcal{DF} \subseteq \mathcal{G}$where $\mathcal{DF}$ set of flexible demand resources
$\mathcal{ELECTROLYZER} \subseteq \mathcal{G}$where $\mathcal{ELECTROLYZER}$ set of electrolyzer resources (optional set)
$\mathcal{G}_p^{ESR} \subseteq \mathcal{G}$where $\mathcal{G}_p^{ESR}$ is a subset of $\mathcal{G}$ that is eligible for Energy Share Requirement (ESR) policy constraint $p$
$p \in \mathcal{P}$where $p$ denotes a instance in the policy set $\mathcal{P}$
$\mathcal{P}^{ESR} \subseteq \mathcal{P}$Energy Share Requirement type policies
$\mathcal{P}^{CO_2} \subseteq \mathcal{P}$CO$_2$ emission cap policies
$\mathcal{P}^{CO_2}_{mass} \subseteq \mathcal{P}^{CO_2}$CO$_2$ emissions limit policy constraints, mass-based
$\mathcal{P}^{CO_2}_{demand} \subseteq \mathcal{P}^{CO_2}$CO$_2$ emissions limit policy constraints, demand and emission-rate based
$\mathcal{P}^{CO_2}_{gen} \subseteq \mathcal{P}^{CO_2}$CO$_2$ emissions limit policy constraints, generation emission-rate based
$\mathcal{P}^{CRM} \subseteq \mathcal{P}$Capacity reserve margin (CRM) type policy constraints
$\mathcal{P}^{MinTech} \subseteq \mathcal{P}$Minimum Capacity Carve-out type policy constraint
$\mathcal{Z}^{ESR}_{p} \subseteq \mathcal{Z}$set of zones eligible for ESR policy constraint $p \in \mathcal{P}^{ESR}$
$\mathcal{Z}^{CRM}_{p} \subseteq \mathcal{Z}$set of zones that form the locational deliverable area for capacity reserve margin policy constraint $p \in \mathcal{P}^{CRM}$
$\mathcal{Z}^{CO_2}_{p,mass} \subseteq \mathcal{Z}$set of zones are under the emission cap mass-based cap-and-trade policy constraint $p \in \mathcal{P}^{CO_2}_{mass}$
$\mathcal{Z}^{CO_2}_{p,demand} \subseteq \mathcal{Z}$set of zones are under the emission cap demand-and-emission-rate based cap-and-trade policy constraint $p \in \mathcal{P}^{CO_2}_{demand}$
$\mathcal{Z}^{CO_2}_{p,gen} \subseteq \mathcal{Z}$set of zones are under the emission cap generation emission-rate based cap-and-trade policy constraint $p \in \mathcal{P}^{CO2,gen}$
$\mathcal{L}_p^{in} \subseteq \mathcal{L}$The subset of transmission lines entering Locational Deliverability Area of capacity reserve margin policy $p \in \mathcal{P}^{CRM}$
$\mathcal{L}_p^{out} \subseteq \mathcal{L}$The subset of transmission lines leaving Locational Deliverability Area of capacity reserve margin policy $p \in \mathcal{P}^{CRM}$
$\mathcal{Qualified} \subseteq \mathcal{G}$where $\mathcal{Qualified}$ is the subset of generation and storage resources eligible to supply electrolyzers within the same zone (optional set)

Decision Variables


NotationDescription
$\Omega_{y,z} \in \mathbb{R}_+$Installed capacity in terms of the number of units (each unit, being of size $\overline{\Omega}_{y,z}^{size}$) of resource $y$ in zone $z$ [Dimensionless] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the grid connection in [MW AC])
$\Omega^{energy}_{y,z} \in \mathbb{R}_+$Installed energy capacity of resource $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the storage component in MWh)
$\Omega^{charge}_{y,z} \in \mathbb{R}_+$Installed charging power capacity of resource $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\Omega^{pv}_{y,z} \in \mathbb{R}_+$Installed solar PV capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\Omega^{wind}_{y,z} \in \mathbb{R}_+$Installed wind capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\Omega^{inv}_{y,z} \in \mathbb{R}_+$Installed inverter capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\Omega^{dc,dis}_{y,z} \in \mathbb{R}_+$Installed storage DC discharge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\Omega^{dc,cha}_{y,z} \in \mathbb{R}_+$Installed storage DC charge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\Omega^{ac,dis}_{y,z} \in \mathbb{R}_+$Installed storage AC discharge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\Omega^{ac,cha}_{y,z} \in \mathbb{R}_+$Installed storage AC charge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\Delta_{y,z} \in \mathbb{R}_+$Retired capacity of technology $y$ from existing capacity in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the grid connection in MW AC)
$\Delta^{energy}_{y,z} \in \mathbb{R}_+$Retired energy capacity of technology $y$ from existing capacity in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the storage component in MWh)
$\Delta^{charge}_{y,z} \in \mathbb{R}_+$Retired charging capacity of technology $y$ from existing capacity in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$[MW]
$\Delta^{pv}_{y,z} \in \mathbb{R}_+$Retired solar PV capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\Delta^{wind}_{y,z} \in \mathbb{R}_+$Retired wind capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\Delta^{inv}_{y,z} \in \mathbb{R}_+$Retired inverter capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\Delta^{dc,dis}_{y,z} \in \mathbb{R}_+$Retired storage DC discharge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\Delta^{dc,cha}_{y,z} \in \mathbb{R}_+$Retired storage DC charge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\Delta^{ac,dis}_{y,z} \in \mathbb{R}_+$Retired storage AC discharge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\Delta^{ac,cha}_{y,z} \in \mathbb{R}_+$Retired storage AC charge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\Delta_{y,z}^{total} \in \mathbb{R}_+$Total installed capacity of technology $y$ in zone $z$ [MW] (Note that co-located VRE and storage resources, this value represents the total capacity of the grid connection in MW AC)
$\Delta_{y,z}^{total,energy} \in \mathbb{R}_+$Total installed energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that co-located VRE and storage resources, this value represents the total installed energy capacity of the storage component in MWh)
$\Delta_{y,z}^{total,charge} \in \mathbb{R}_+$Total installed charging power capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\Delta_{y,z}^{total,pv} \in \mathbb{R}_+$Total installed solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\Delta_{y,z}^{total,wind} \in \mathbb{R}_+$Total installed wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\Delta_{y,z}^{total,inv} \in \mathbb{R}_+$Total installed inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\Delta_{y,z}^{total,dc,dis} \in \mathbb{R}_+$Total installed storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\Delta_{y,z}^{total,dc,cha} \in \mathbb{R}_+$Total installed storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\Delta_{y,z}^{total,ac,dis} \in \mathbb{R}_+$Total installed storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\Delta_{y,z}^{total,ac,cha} \in \mathbb{R}_+$Total installed storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\bigtriangleup\varphi^{max}_{l}$Additional transmission capacity added to line $l$ [MW]
$\Theta_{y,z,t} \in \mathbb{R}_+$Energy injected into the grid by technology $y$ at time step $t$ in zone $z$ [MWh]
$\Theta^{pv}_{y,z,t} \in \mathbb{R}_+$Energy generated by the solar PV component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MWh]
$\Theta^{wind}_{y,z,t} \in \mathbb{R}_+$Energy generated by the wind component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MWh]
$\Theta^{dc}_{y,z,t} \in \mathbb{R}_+$Energy discharged by the storage DC component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a discharge DC component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$ [MWh]
$\Theta^{ac}_{y,z,t} \in \mathbb{R}_+$Energy discharged by the storage AC component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a discharge AC component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$ [MWh]
$\Pi_{y,z,t} \in \mathbb{R}_+$Energy withdrawn from grid by technology $y$ at time step $t$ in zone $z$ [MWh]
$\Pi^{dc}_{y,z,t} \in \mathbb{R}_+$Energy withdrawn from the VRE and grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a charge DC component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$ [MWh]
$\Pi^{ac}_{y,z,t} \in \mathbb{R}_+$Energy withdrawn from the VRE and grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a charge AC component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$ [MWh]
$\Gamma_{y,z,t} \in \mathbb{R}_+$Stored energy level of technology $y$ at end of time step $t$ in zone $z$ [MWh]
$\Lambda_{s,z,t} \in \mathbb{R}_+$Non-served energy/curtailed demand from the price-responsive demand segment $s$ in zone $z$ at time step $t$ [MWh]
$l_{l,t} \in \mathbb{R}_+$Losses in line $l$ at time step $t$ [MWh]
$\varrho_{y,z,t}\in \mathbb{R}_+$Spillage from a reservoir technology $y$ at end of time step $t$ in zone $z$ [MWh]
$f_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves from technology $y$ in zone $z$ at time $t$\footnote{Regulation reserve contribution are modeled to be symmetric, consistent with current practice in electricity markets}
$r_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] from technology $y$ in zone $z$ at time t (we are not modeling down spinning reserves since these are usually never binding for high variable renewable energy systems)
$f^{charge}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves from charging storage technology $y$ in zone $z$ at time $t$
$f^{discharge}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves from discharging storage technology $y$ in zone $z$ at time $t$
$r^{charge}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] from charging storage technology $y$ in zone $z$ at time $t$
$r^{discharge}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] from discharging storage technology $y$ in zone $z$ at time $t$
$r^{unmet}_t \in \mathbb{R}_+$Shortfall in provision of upward operating spinning reserves during each time period $t \in T$
$f^{pv}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the solar PV component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$
$r^{pv}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the solar PV component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$
$f^{wind}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the wind component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$
$r^{wind}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the wind component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$
$f^{dc,dis}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage DC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$
$r^{dc,dis}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage DC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$
$f^{dc,cha}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage DC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$
$r^{dc,cha}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage DC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$
$f^{ac,dis}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage AC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$
$r^{ac,dis}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage AC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$
$f^{ac,cha}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage AC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$
$r^{ac,cha}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage AC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$
$\alpha^{Contingency,Aux}_{y,z} \in \{0,1\}$Binary variable that is set to be 1 if the total installed capacity $\Delta^{\text{total}}_{y,z} > 0$ for any generator $y \in \mathcal{UC}$ and zone $z$, and can be 0 otherwise
$\Phi_{l,t} \in \mathbb{R}_+$Power flow in line $l$ at time step $t$ [MWh]
$\theta_{z,t} \in \mathbb{R}$Volta phase angle in zone $z$ at time step $t$ [radian]
$v_{y,z,t}$Commitment state of the generation cluster $y$ in zone $z$ at time $t$
$\mathcal{X}_{y,z,t}$Number of startup decisions, of the generation cluster $y$ in zone $z$ at time $t$
$\zeta_{y,z,t}$Number of shutdown decisions, of the generation cluster $y$ in zone $z$ at time $t$
$\mathcal{Q}_{o,n} \in \mathbb{R}_+$Inventory of storage of type $o$ at the beginning of input period $n$ [MWh]
$\Delta\mathcal{Q}_{o,m} \in \mathbb{R}$Excess storage inventory built up during representative period $m$ [MWh]
$ON^{+}_{l,t} \in {0,1}$Binary variable to activate positive flows on line $l$ in time $t$
$TransON^{+}_{l,t} \in \mathbb{R}_+$Variable defining maximum positive flow in line $l$ in time $t$ [MW]
$\Theta^{CRM}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy discharged by a storage resource that contributes to the capacity reserve margin for technology $y$ at time step $t$ in zone $z$ - only applicable for storage resources with activated capacity reserve margin policies, $y \in \mathcal{O}$ [MWh]
$\Pi^{CRM}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy withdrawn by a storage resource from the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for storage resources with activated capacity reserve margin policies, $y \in \mathcal{O}$ [MWh]
$\Theta^{CRM,dc}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy discharged by a storage DC component that contributes to the capacity reserve margin for technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Pi^{CRM,dc}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy withdrawn by a storage DC component from the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Theta^{CRM,ac}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy discharged by a storage AC component that contributes to the capacity reserve margin for technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Pi^{CRM,ac}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy withdrawn by a storage AC component from the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Gamma^{CRM}_{y,z,t} \in \mathbb{R}_+$Total "virtual" state of charge being held in reserves for technology $y$ at time step $t$ in zone $z$ - only applicable for standalone storage and co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh]

Parameters


NotationDescription
$D_{z,t}$Electricity demand in zone $z$ and at time step $t$ [MWh]
$\tau^{period}$number of time steps in each representative period $w \in \mathcal{W}^{rep}$ and each input period $w \in \mathcal{W}^{input}$
$\omega_{t}$weight of each model time step $\omega_t =1 \forall t \in T$ when modeling each time step of the year at an hourly resolution [1/year]
$n_s^{slope}$Cost of non-served energy/demand curtailment for price-responsive demand segment $s$ [$/MWh]
$n_s^{size}$Size of price-responsive demand segment $s$ as a fraction of the hourly zonal demand [%]
$\overline{\Omega}_{y,z}$Maximum capacity of technology $y$ in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the maximum grid connection capacity in MW AC)
$\underline{\Omega}_{y,z}$Minimum capacity of technology $y$ in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the minimum grid connection capacity in MW AC)
$\overline{\Omega}^{energy}_{y,z}$Maximum energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the maximum storage component in MWh)
$\underline{\Omega}^{energy}_{y,z}$Minimum energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the minimum storage component in MWh)
$\overline{\Omega}^{charge}_{y,z}$Maximum charging power capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\underline{\Omega}^{charge}_{y,z}$Minimum charging capacity of technology $y$ in zone $z$- only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\overline{\Omega}^{pv}_{y,z}$Maximum solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\underline{\Omega}^{pv}_{y,z}$Minimum solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\overline{\Omega}^{wind}_{y,z}$Maximum wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\underline{\Omega}^{wind}_{y,z}$Minimum wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\overline{\Omega}^{inv}_{y,z}$Maximum inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\underline{\Omega}^{inv}_{y,z}$Minimum inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\overline{\Omega}^{dc,dis}_{y,z}$Maximum storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\underline{\Omega}^{dc,dis}_{y,z}$Minimum storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\overline{\Omega}^{dc,cha}_{y,z}$Maximum storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\underline{\Omega}^{dc,cha}_{y,z}$Minimum storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\overline{\Omega}^{ac,dis}_{y,z}$Maximum storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\underline{\Omega}^{ac,dis}_{y,z}$Minimum storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\overline{\Omega}^{ac,cha}_{y,z}$Maximum storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\underline{\Omega}^{ac,cha}_{y,z}$Minimum storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\overline{\Delta}_{y,z}$Existing installed capacity of technology $y$ in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the existing installed capacity of the grid connection in [MW AC])
$\overline{\Delta^{energy}_{y,z}}$Existing installed energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the existing installed energy capacity of the storage component in MWh)
$\overline{\Delta^{charge}_{y,z}}$Existing installed charging capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}$ [MW]
$\overline{\Delta^{pv}_{y,z}}$Existing installed solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\overline{\Delta^{wind}_{y,z}}$Existing installed wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\overline{\Delta^{inv}_{y,z}}$Existing installed inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\overline{\Delta^{dc,dis}_{y,z}}$Existing installed storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\overline{\Delta^{dc,cha}_{y,z}}$Existing installed storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\overline{\Delta^{ac,dis}_{y,z}}$Existing installed storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\overline{\Delta^{dc,cha}_{y,z}}$Existing installed storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW AC]
$\overline{\Omega}_{y,z}^{size}$Unit size of technology $y$ in zone $z$ [MW]
$\pi_{y,z}^{INVEST}$Investment cost (annual amortization of total construction cost) for power capacity of technology $y$ in zone $z$ [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the grid connection capacity in $/MW AC-yr)
$\pi_{y,z}^{INVEST,energy}$Investment cost (annual amortization of total construction cost) for energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{pv}$ [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the energy capacity of the storage component in $/MWh-yr)
$\pi_{y,z}^{INVEST,charge}$Investment cost (annual amortization of total construction cost) for charging power capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}$ [$/MW-yr]
$\pi_{y,z}^{INVEST,pv}$Investment cost (annual amortization of total construction cost) for solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [$/MW DC-yr]
$\pi_{y,z}^{INVEST,wind}$Investment cost (annual amortization of total construction cost) for wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [$/MW AC-yr]
$\pi_{y,z}^{INVEST,inv}$Investment cost (annual amortization of total construction cost) for inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [$/MW AC-yr]
$\pi_{y,z}^{INVEST,dc,dis}$Investment cost (annual amortization of total construction cost) for storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [$/MW DC-yr]
$\pi_{y,z}^{INVEST,dc,cha}$Investment cost (annual amortization of total construction cost) for storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [$/MW DC-yr]
$\pi_{y,z}^{INVEST,ac,dis}$Investment cost (annual amortization of total construction cost) for storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [$/MW AC-yr]
$\pi_{y,z}^{INVEST,ac,cha}$Investment cost (annual amortization of total construction cost) for storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM}$Fixed O&M cost of technology $y$ in zone $z$ [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the grid connection capacity in $/MW AC-yr)
$\pi_{y,z}^{FOM,energy}$Fixed O&M cost of energy component of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the storage energy capacity in $/MWh-yr)
$\pi_{y,z}^{FOM,charge}$Fixed O&M cost of charging power component of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}$ [$/MW-yr]
$\pi_{y,z}^{FOM,pv}$Fixed O&M cost of the solar PV component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [$/MW DC-yr]
$\pi_{y,z}^{FOM,wind}$Fixed O&M cost of the wind component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM,inv}$Fixed O&M cost of the inverter component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM,dc,dis}$Fixed O&M cost of the storage DC discharge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [$/MW DC-yr]
$\pi_{y,z}^{FOM,dc,cha}$Fixed O&M cost of the storage DC charge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [$/MW DC-yr]
$\pi_{y,z}^{FOM,ac,dis}$Fixed O&M cost of the storage AC discharge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM,ac,cha}$Fixed O&M cost of the storage AC charge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [$/MW AC-yr]
$\pi_{y,z}^{VOM}$Variable O&M cost of technology $y$ in zone $z$ [$/MWh]
$\pi_{y,z}^{VOM,charge}$Variable O&M cost of charging technology $y$ in zone $z$ - only applicable for storage and demand flexibility resources, $y \in \mathcal{O} \cup \mathcal{DF}$ [$/MWh]
$\pi_{y,z}^{VOM,pv}$Variable O&M cost of the solar PV component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [$/MWh]
$\pi_{y,z}^{VOM,wind}$Variable O&M cost of the wind component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [$/MWh]
$\pi_{y,z}^{VOM,dc,dis}$Variable O&M cost of the storage DC discharge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$ [$/MWh]
$\pi_{y,z}^{VOM,dc,cha}$Variable O&M cost of the storage DC charge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$ [$/MWh]
$\pi_{y,z}^{VOM,ac,dis}$Variable O&M cost of the storage AC discharge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$ [$/MWh]
$\pi_{y,z}^{VOM,ac,cha}$Variable O&M cost of the storage AC charge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$ [$/MWh]
$\pi_{y,z}^{FUEL}$Fuel cost of technology $y$ in zone $z$ [$/MWh]
$\pi_{y,z}^{START}$Startup cost of technology $y$ in zone $z$ [$/startup]
$\upsilon^{reg}_{y,z}$Maximum fraction of capacity that a resource $y$ in zone $z$ can contribute to frequency regulation reserve requirements
$\upsilon^{rsv}_{y,z}$Maximum fraction of capacity that a resource $y$ in zone $z$ can contribute to upward operating (spinning) reserve requirements
$\pi^{Unmet}_{rsv}$Cost of unmet spinning reserves in [$/MW]
$\epsilon^{demand}_{reg}$Frequency regulation reserve requirement as a fraction of forecasted demand in each time step
$\epsilon^{vre}_{reg}$Frequency regulation reserve requirement as a fraction of variable renewable energy generation in each time step
$\epsilon^{demand}_{rsv}$Operating (spinning) reserve requirement as a fraction of forecasted demand in each time step
$\epsilon^{vre}_{rsv}$Operating (spinning) reserve requirement as a fraction of forecasted variable renewable energy generation in each time step
$\epsilon_{y,z}^{CO_2}$CO$_2$ emissions per unit energy produced by technology $y$ in zone $z$ [metric tons/MWh]
$\epsilon_{y,z,p}^{MinTech}$Equals to 1 if a generator of technology $y$ in zone $z$ is eligible for minimum capacity carveout policy $p \in \mathcal{P}^{MinTech}$, otherwise 0
$REQ_p^{MinTech}$The minimum capacity requirement of minimum capacity carveout policy $p \in \mathcal{P}^{MinTech}$ [MW]
$REQ_p^{MaxTech}$The maximum capacity requirement of minimum capacity carveout policy $p \in \mathcal{P}^{MinTech}$ [MW]
$\epsilon_{y,z,p}^{CRM}$Capacity derating factor of technology $y$ in zone $z$ for capacity reserve margin policy $p \in \mathcal{P}^{CRM}$ [fraction]
$RM_{z,p}^{CRM}$Reserve margin of zone $z$ of capacity reserve margin policy $p \in \mathcal{P}^{CRM}$ [fraction]
$\epsilon_{z,p,mass}^{CO_2}$Emission budget of zone $z$ under the emission cap $p \in \mathcal{P}^{CO_2}_{mass}$ [ million of metric tonnes]
$\epsilon_{z,p,demand}^{CO_2}$Maximum carbon intensity of the demand of zone $z$ under the emission cap $p \in \mathcal{P}^{CO_2}_{demand}$ [metric tonnes/MWh]
$\epsilon_{z,p,gen}^{CO_2}$Maximum emission rate of the generation of zone $z$ under the emission cap $p \in \mathcal{P}^{CO_2}_{gen}$ [metric tonnes/MWh]
$\rho_{y,z}^{min}$Minimum stable power output per unit of installed capacity for technology $y$ in zone $z$ [%]
$\rho_{y,z,t}^{max}$Maximum available generation per unit of installed capacity during time step t for technology y in zone z [%]
$\rho_{y,z,t}^{max,pv}$Maximum available generation per unit of installed capacity for the solar PV component of a co-located VRE and storage resource during time step t for technology y in zone z [%]
$\rho_{y,z,t}^{max,wind}$Maximum available generation per unit of installed capacity for the wind component of a co-located VRE and storage resource during time step t for technology y in zone z [%]
$VREIndex_{y,z}$Resource bin index for VRE technology $y$ in zone $z$. $VREIndex_{y,z}=1$ for the first bin, and $VREIndex_{y,z}=0$ for remaining bins. Only defined for $y\in \mathcal{VRE}$
$\varphi^{map}_{l,z}$Topology of the network, for line l: $\varphi^{map}_{l,z}=1$ for start zone $z$, - 1 for end zone $z$, 0 otherwise.
$\mathcal{B}_{l}$DC-OPF coefficient for line $l$ [MWh]
$\Delta \theta^{\max}_{l}$Maximum voltage phase angle difference for line $l$ [radian]
$\eta_{y,z}^{loss}$Self discharge rate per time step per unit of installed capacity for storage technology $y$ in zone $z$ [%]
$\eta_{y,z}^{charge}$Single-trip efficiency of storage charging/demand deferral for technology $y$ in zone $z$ [%]
$\eta_{y,z}^{discharge}$Single-trip efficiency of storage (and hydro reservoir) discharging/demand satisfaction for technology $y$ in zone $z$ [%]
$\eta_{y,z}^{charge,dc}$Single-trip efficiency of storage DC charging/demand deferral for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{discharge,dc}$Single-trip efficiency of storage DC discharging/demand satisfaction for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{charge,ac}$Single-trip efficiency of storage AC charging/demand deferral for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{discharge,ac}$Single-trip efficiency of storage AC discharging/demand satisfaction for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{inverter}$Inverter efficiency representing losses from converting DC to AC power and vice versa for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{ILR,pv}$Inverter loading ratio (the solar PV capacity sizing to the inverter capacity built) of technology $y$ in zone $z$ for co-located VRE and storage resources with a solar PV component [%]
$\eta_{y,z}^{ILR,wind}$Inverter loading ratio (the wind PV capacity sizing to the grid connection capacity built) of technology $y$ in zone $z$ for co-located VRE and storage resources with a wind component [%]
$\mu_{y,z}^{stor}$Ratio of energy capacity to discharge power capacity for storage technology (and hydro reservoir) $y$ in zone $z$ [MWh/MW]
$\mu_{y,z}^{dc,stor}$Ratio of discharge power capacity to energy capacity for the storage DC component of co-located VRE and storage technology $y$ in zone $z$ [MW/MWh]
$\mu_{y,z}^{ac,stor}$Ratio of discharge power capacity to energy capacity for the storage AC component of co-located VRE and storage technology $y$ in zone $z$ [MW/MWh]
$\mu_{y,z}^{\mathcal{DF}}$Maximum percentage of hourly demand that can be shifted by technology $y$ in zone $z$ [%]
$\kappa_{y,z}^{up}$Maximum ramp-up rate per time step as percentage of installed capacity of technology y in zone z [%/hr]
$\kappa_{y,z}^{down}$Maximum ramp-down rate per time step as percentage of installed capacity of technology y in zone z [%/hr]
$\tau_{y,z}^{up}$Minimum uptime for thermal generator type y in zone z before new shutdown [hours].
$\tau_{y,z}^{down}$Minimum downtime or thermal generator type y in zone z before new restart [hours].
$\tau_{y,z}^{advance}$maximum time by which flexible demand resource can be advanced [hours]
$\tau_{y,z}^{delay}$maximum time by which flexible demand resource can be delayed [hours]
$\eta_{y,z}^{dflex}$energy losses associated with shifting the flexible demand [%]
$\mu_{p,z}^{\mathcal{ESR}}$share of total demand in each model zone $z \in \mathcal{ESR}^{p}$ that must be served by qualifying renewable energy resources $y \in \mathcal{G}^{ESR}_{p}$
$f(n)$Mapping each modeled period $n \in \mathcal{N}$ to corresponding representative period $w \in \mathcal{W}$
$\eta_{y}^{electrolyzer}$Efficiency of the electrolyzer $y$ in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced [MWh/t] (optional parameter)
$ $^{hydrogen}_y$Price of hydrogen per metric tonne for electrolyzer $y$ [$/t] (optional parameter)
$\mathcal{Min kt}_y$Minimum annual quantity of hydrogen that must be produced by electrolyzer $y$ in kilotonnes [kt] (optional parameter)

+Notation · GenX

Model Notation

Model Indices and Sets


NotationDescription
$t \in \mathcal{T}$where $t$ denotes an time step and $\mathcal{T}$ is the set of time steps over which grid operations are modeled
$\mathcal{T}^{interior} \subseteq \mathcal{T}^{}$where $\mathcal{T}^{interior}$ is the set of interior timesteps in the data series
$\mathcal{T}^{start} \subseteq \mathcal{T}$where $\mathcal{T}^{start}$ is the set of initial timesteps in the data series. $\mathcal{T}^{start}={1}$ when representing entire year as a single contiguous period; $\mathcal{T}^{start}=\{\left(m-1\right) \times \tau^{period}+1 | m \in \mathcal{M}\}$, which corresponds to the first time step of each representative period $m \in \mathcal{M}$
$n \in \mathcal{N}$where $n$ corresponds to a contiguous time period and $\mathcal{N}$ corresponds to the set of contiguous periods of length $\tau^{period}$ that make up the input time series (e.g. demand, variable renewable energy availability) to the model
$\mathcal{N}^{rep} \subseteq \mathcal{N}$where $\mathcal{N}^{rep}$ corresponds to the set of representative time periods that are selected from the set of contiguous periods, $\mathcal{M}$
$m \in \mathcal{M}$where $m$ corresponds to a representative time period and $\mathcal{M}$ corresponds to the set of representative time periods indexed as per their chronological ocurrence in the set of contiguous periods spanning the input time series data, i.e. $\mathcal{N}$
$z \in \mathcal{Z}$where $z$ denotes a zone and $\mathcal{Z}$ is the set of zones in the network
$l \in \mathcal{L}$where $l$ denotes a line and $\mathcal{L}$ is the set of transmission lines in the network
$y \in \mathcal{G}$where $y$ denotes a technology and $\mathcal{G}$ is the set of available technologies
$\mathcal{H} \subseteq \mathcal{G}$where $\mathcal{H}$ is the subset of thermal resources
$\mathcal{VRE} \subseteq \mathcal{G}$where $\mathcal{VRE}$ is the subset of curtailable Variable Renewable Energy (VRE) resources
$\overline{\mathcal{VRE}}^{y,z}$set of VRE resource bins for VRE technology type $y \in \mathcal{VRE}$ in zone $z$
$\mathcal{CE} \subseteq \mathcal{G}$where $\mathcal{CE}$ is the subset of resources qualifying for the clean energy standard policy constraint
$\mathcal{UC} \subseteq \mathcal{H}$where $\mathcal{UC}$ is the subset of thermal resources subject to unit commitment constraints
$s \in \mathcal{S}$where $s$ denotes a segment and $\mathcal{S}$ is the set of consumers segments for price-responsive demand curtailment
$\mathcal{O} \subseteq \mathcal{G}$where $\mathcal{O}$ is the subset of storage resources excluding heat storage and hydro storage
$o \in \mathcal{O}$where $o$ denotes a storage technology in a set $\mathcal{O}$
$\mathcal{O}^{sym} \subseteq \mathcal{O}$where $\mathcal{O}^{sym}$ corresponds to the set of energy storage technologies with equal (or symmetric) charge and discharge power capacities
$\mathcal{O}^{asym} \subseteq \mathcal{O}$where $\mathcal{O}^{asym}$ corresponds to the set of energy storage technologies with independently sized (or asymmetric) charge and discharge power capacities
$\mathcal{O}^{LDES} \subseteq \mathcal{O}$where $\mathcal{O}^{LDES}$ corresponds to the set of long-duration energy storage technologies for which inter-period energy exchange is permitted when using representative periods to model annual grid operations
$\mathcal{VS} \subseteq \mathcal{G}$where $\mathcal{VS}$ is the subset of co-located VRE and storage resources
$\mathcal{VS}^{pv} \subseteq \mathcal{VS}$where $\mathcal{VS}^{pv}$ corresponds to the set of co-located VRE and storage resources with a solar PV component
$\mathcal{VS}^{wind} \subseteq \mathcal{VS}$where $\mathcal{VS}^{wind}$ corresponds to the set of co-located VRE and storage resources with a wind component
$\mathcal{VS}^{inv} \subseteq \mathcal{VS}$where $\mathcal{VS}^{inv}$ corresponds to the set of co-located VRE and storage resources with an inverter component
$\mathcal{VS}^{stor} \subseteq \mathcal{VS}$where $\mathcal{VS}^{stor}$ corresponds to the set of co-located VRE and storage resources with a storage component
$\mathcal{VS}^{sym, dc} \subseteq \mathcal{VS}$where $\mathcal{VS}^{sym, dc}$ corresponds to the set of co-located VRE and storage resources with a storage DC component with equal (or symmetric) charge and discharge power capacities
$\mathcal{VS}^{sym, ac} \subseteq \mathcal{VS}$where $\mathcal{VS}^{sym, ac}$ corresponds to the set of co-located VRE and storage resources with a storage AC component with equal (or symmetric) charge and discharge power capacities
$\mathcal{VS}^{asym, dc, dis} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, dc, dis}$ corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) discharge power capabilities
$\mathcal{VS}^{asym, dc, cha} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, dc, cha}$ corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) charge power capabilities
$\mathcal{VS}^{asym, ac, dis} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, ac, dis}$ corresponds to the set of co-located VRE and storage with a storage AC component with independently sized (or asymmetric) discharge power capabilities
$\mathcal{VS}^{asym, ac, cha} \subseteq \mathcal{VS}$where $\mathcal{VS}^{asym, ac, cha}$ corresponds to the set of co-located VRE and storage resources with a storage AC component with independently sized (or asymmetric) charge power capabilities
$\mathcal{VS}^{LDES} \subseteq \mathcal{VS}$where $\mathcal{VS}^{LDES}$ corresponds to the set of co-located VRE and storage resources with a long-duration energy storage component for which inter-period energy exchange is permitted when using representative periods to model annual grid operations
$\mathcal{W} \subseteq \mathcal{G}$where $\mathcal{W}$ set of hydroelectric generators with water storage reservoirs
$\mathcal{W}^{nocap} \subseteq \mathcal{W}$where $\mathcal{W}^{nocap}$ is a subset of set of $ \mathcal{W}$ and represents resources with unknown reservoir capacity
$\mathcal{W}^{cap} \subseteq \mathcal{W}$where $\mathcal{W}^{cap}$ is a subset of set of $ \mathcal{W}$ and represents resources with known reservoir capacity
$\mathcal{MR} \subseteq \mathcal{G}$where $\mathcal{MR}$ set of must-run resources
$\mathcal{DF} \subseteq \mathcal{G}$where $\mathcal{DF}$ set of flexible demand resources
$\mathcal{ELECTROLYZER} \subseteq \mathcal{G}$where $\mathcal{ELECTROLYZER}$ set of electrolyzer resources (optional set)
$\mathcal{G}_p^{ESR} \subseteq \mathcal{G}$where $\mathcal{G}_p^{ESR}$ is a subset of $\mathcal{G}$ that is eligible for Energy Share Requirement (ESR) policy constraint $p$
$p \in \mathcal{P}$where $p$ denotes a instance in the policy set $\mathcal{P}$
$\mathcal{P}^{ESR} \subseteq \mathcal{P}$Energy Share Requirement type policies
$\mathcal{P}^{CO_2} \subseteq \mathcal{P}$CO$_2$ emission cap policies
$\mathcal{P}^{CO_2}_{mass} \subseteq \mathcal{P}^{CO_2}$CO$_2$ emissions limit policy constraints, mass-based
$\mathcal{P}^{CO_2}_{demand} \subseteq \mathcal{P}^{CO_2}$CO$_2$ emissions limit policy constraints, demand and emission-rate based
$\mathcal{P}^{CO_2}_{gen} \subseteq \mathcal{P}^{CO_2}$CO$_2$ emissions limit policy constraints, generation emission-rate based
$\mathcal{P}^{CRM} \subseteq \mathcal{P}$Capacity reserve margin (CRM) type policy constraints
$\mathcal{P}^{MinTech} \subseteq \mathcal{P}$Minimum Capacity Carve-out type policy constraint
$\mathcal{Z}^{ESR}_{p} \subseteq \mathcal{Z}$set of zones eligible for ESR policy constraint $p \in \mathcal{P}^{ESR}$
$\mathcal{Z}^{CRM}_{p} \subseteq \mathcal{Z}$set of zones that form the locational deliverable area for capacity reserve margin policy constraint $p \in \mathcal{P}^{CRM}$
$\mathcal{Z}^{CO_2}_{p,mass} \subseteq \mathcal{Z}$set of zones are under the emission cap mass-based cap-and-trade policy constraint $p \in \mathcal{P}^{CO_2}_{mass}$
$\mathcal{Z}^{CO_2}_{p,demand} \subseteq \mathcal{Z}$set of zones are under the emission cap demand-and-emission-rate based cap-and-trade policy constraint $p \in \mathcal{P}^{CO_2}_{demand}$
$\mathcal{Z}^{CO_2}_{p,gen} \subseteq \mathcal{Z}$set of zones are under the emission cap generation emission-rate based cap-and-trade policy constraint $p \in \mathcal{P}^{CO2,gen}$
$\mathcal{L}_p^{in} \subseteq \mathcal{L}$The subset of transmission lines entering Locational Deliverability Area of capacity reserve margin policy $p \in \mathcal{P}^{CRM}$
$\mathcal{L}_p^{out} \subseteq \mathcal{L}$The subset of transmission lines leaving Locational Deliverability Area of capacity reserve margin policy $p \in \mathcal{P}^{CRM}$
$\mathcal{Qualified} \subseteq \mathcal{G}$where $\mathcal{Qualified}$ is the subset of generation and storage resources eligible to supply electrolyzers within the same zone (optional set)

Decision Variables


NotationDescription
$\Omega_{y,z} \in \mathbb{R}_+$Installed capacity in terms of the number of units (each unit, being of size $\overline{\Omega}_{y,z}^{size}$) of resource $y$ in zone $z$ [Dimensionless] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the grid connection in [MW AC])
$\Omega^{energy}_{y,z} \in \mathbb{R}_+$Installed energy capacity of resource $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the storage component in MWh)
$\Omega^{charge}_{y,z} \in \mathbb{R}_+$Installed charging power capacity of resource $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\Omega^{pv}_{y,z} \in \mathbb{R}_+$Installed solar PV capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\Omega^{wind}_{y,z} \in \mathbb{R}_+$Installed wind capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\Omega^{inv}_{y,z} \in \mathbb{R}_+$Installed inverter capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\Omega^{dc,dis}_{y,z} \in \mathbb{R}_+$Installed storage DC discharge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\Omega^{dc,cha}_{y,z} \in \mathbb{R}_+$Installed storage DC charge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\Omega^{ac,dis}_{y,z} \in \mathbb{R}_+$Installed storage AC discharge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\Omega^{ac,cha}_{y,z} \in \mathbb{R}_+$Installed storage AC charge capacity of resource $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\Delta_{y,z} \in \mathbb{R}_+$Retired capacity of technology $y$ from existing capacity in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the grid connection in MW AC)
$\Delta^{energy}_{y,z} \in \mathbb{R}_+$Retired energy capacity of technology $y$ from existing capacity in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the storage component in MWh)
$\Delta^{charge}_{y,z} \in \mathbb{R}_+$Retired charging capacity of technology $y$ from existing capacity in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$[MW]
$\Delta^{pv}_{y,z} \in \mathbb{R}_+$Retired solar PV capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\Delta^{wind}_{y,z} \in \mathbb{R}_+$Retired wind capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\Delta^{inv}_{y,z} \in \mathbb{R}_+$Retired inverter capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\Delta^{dc,dis}_{y,z} \in \mathbb{R}_+$Retired storage DC discharge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\Delta^{dc,cha}_{y,z} \in \mathbb{R}_+$Retired storage DC charge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\Delta^{ac,dis}_{y,z} \in \mathbb{R}_+$Retired storage AC discharge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\Delta^{ac,cha}_{y,z} \in \mathbb{R}_+$Retired storage AC charge capacity of technology $y$ from existing capacity in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\Delta_{y,z}^{total} \in \mathbb{R}_+$Total installed capacity of technology $y$ in zone $z$ [MW] (Note that co-located VRE and storage resources, this value represents the total capacity of the grid connection in MW AC)
$\Delta_{y,z}^{total,energy} \in \mathbb{R}_+$Total installed energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that co-located VRE and storage resources, this value represents the total installed energy capacity of the storage component in MWh)
$\Delta_{y,z}^{total,charge} \in \mathbb{R}_+$Total installed charging power capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\Delta_{y,z}^{total,pv} \in \mathbb{R}_+$Total installed solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\Delta_{y,z}^{total,wind} \in \mathbb{R}_+$Total installed wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\Delta_{y,z}^{total,inv} \in \mathbb{R}_+$Total installed inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\Delta_{y,z}^{total,dc,dis} \in \mathbb{R}_+$Total installed storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\Delta_{y,z}^{total,dc,cha} \in \mathbb{R}_+$Total installed storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\Delta_{y,z}^{total,ac,dis} \in \mathbb{R}_+$Total installed storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\Delta_{y,z}^{total,ac,cha} \in \mathbb{R}_+$Total installed storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\bigtriangleup\varphi^{max}_{l}$Additional transmission capacity added to line $l$ [MW]
$\Theta_{y,z,t} \in \mathbb{R}_+$Energy injected into the grid by technology $y$ at time step $t$ in zone $z$ [MWh]
$\Theta^{pv}_{y,z,t} \in \mathbb{R}_+$Energy generated by the solar PV component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MWh]
$\Theta^{wind}_{y,z,t} \in \mathbb{R}_+$Energy generated by the wind component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MWh]
$\Theta^{dc}_{y,z,t} \in \mathbb{R}_+$Energy discharged by the storage DC component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a discharge DC component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$ [MWh]
$\Theta^{ac}_{y,z,t} \in \mathbb{R}_+$Energy discharged by the storage AC component into the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a discharge AC component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$ [MWh]
$\Pi_{y,z,t} \in \mathbb{R}_+$Energy withdrawn from grid by technology $y$ at time step $t$ in zone $z$ [MWh]
$\Pi^{dc}_{y,z,t} \in \mathbb{R}_+$Energy withdrawn from the VRE and grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a charge DC component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$ [MWh]
$\Pi^{ac}_{y,z,t} \in \mathbb{R}_+$Energy withdrawn from the VRE and grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with a charge AC component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$ [MWh]
$\Gamma_{y,z,t} \in \mathbb{R}_+$Stored energy level of technology $y$ at end of time step $t$ in zone $z$ [MWh]
$\Lambda_{s,z,t} \in \mathbb{R}_+$Non-served energy/curtailed demand from the price-responsive demand segment $s$ in zone $z$ at time step $t$ [MWh]
$l_{l,t} \in \mathbb{R}_+$Losses in line $l$ at time step $t$ [MWh]
$\varrho_{y,z,t}\in \mathbb{R}_+$Spillage from a reservoir technology $y$ at end of time step $t$ in zone $z$ [MWh]
$f_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves from technology $y$ in zone $z$ at time $t$\footnote{Regulation reserve contribution are modeled to be symmetric, consistent with current practice in electricity markets}
$r_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] from technology $y$ in zone $z$ at time t (we are not modeling down spinning reserves since these are usually never binding for high variable renewable energy systems)
$f^{charge}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves from charging storage technology $y$ in zone $z$ at time $t$
$f^{discharge}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves from discharging storage technology $y$ in zone $z$ at time $t$
$r^{charge}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] from charging storage technology $y$ in zone $z$ at time $t$
$r^{discharge}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] from discharging storage technology $y$ in zone $z$ at time $t$
$r^{unmet}_t \in \mathbb{R}_+$Shortfall in provision of upward operating spinning reserves during each time period $t \in T$
$f^{pv}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the solar PV component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$
$r^{pv}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the solar PV component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$
$f^{wind}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the wind component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$
$r^{wind}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the wind component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$
$f^{dc,dis}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage DC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$
$r^{dc,dis}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage DC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$
$f^{dc,cha}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage DC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$
$r^{dc,cha}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage DC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$
$f^{ac,dis}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage AC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$
$r^{ac,dis}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage AC discharge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$
$f^{ac,cha}_{y,z,t}\in \mathbb{R}_+$Frequency regulation contribution [MW] for up and down reserves for the storage AC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$
$r^{ac,cha}_{y,z,t} \in \mathbb{R}_+$Upward spinning reserves contribution [MW] for the storage AC charge component from technology $y$ in zone $z$ at time $t$ - only applicable for co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$
$\alpha^{Contingency,Aux}_{y,z} \in \{0,1\}$Binary variable that is set to be 1 if the total installed capacity $\Delta^{\text{total}}_{y,z} > 0$ for any generator $y \in \mathcal{UC}$ and zone $z$, and can be 0 otherwise
$\Phi_{l,t} \in \mathbb{R}_+$Power flow in line $l$ at time step $t$ [MWh]
$\theta_{z,t} \in \mathbb{R}$Volta phase angle in zone $z$ at time step $t$ [radian]
$v_{y,z,t}$Commitment state of the generation cluster $y$ in zone $z$ at time $t$
$\mathcal{X}_{y,z,t}$Number of startup decisions, of the generation cluster $y$ in zone $z$ at time $t$
$\zeta_{y,z,t}$Number of shutdown decisions, of the generation cluster $y$ in zone $z$ at time $t$
$\mathcal{Q}_{o,n} \in \mathbb{R}_+$Inventory of storage of type $o$ at the beginning of input period $n$ [MWh]
$\Delta\mathcal{Q}_{o,m} \in \mathbb{R}$Excess storage inventory built up during representative period $m$ [MWh]
$ON^{+}_{l,t} \in {0,1}$Binary variable to activate positive flows on line $l$ in time $t$
$TransON^{+}_{l,t} \in \mathbb{R}_+$Variable defining maximum positive flow in line $l$ in time $t$ [MW]
$\Theta^{CRM}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy discharged by a storage resource that contributes to the capacity reserve margin for technology $y$ at time step $t$ in zone $z$ - only applicable for storage resources with activated capacity reserve margin policies, $y \in \mathcal{O}$ [MWh]
$\Pi^{CRM}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy withdrawn by a storage resource from the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for storage resources with activated capacity reserve margin policies, $y \in \mathcal{O}$ [MWh]
$\Theta^{CRM,dc}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy discharged by a storage DC component that contributes to the capacity reserve margin for technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Pi^{CRM,dc}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy withdrawn by a storage DC component from the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Theta^{CRM,ac}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy discharged by a storage AC component that contributes to the capacity reserve margin for technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Pi^{CRM,ac}_{y,z,t} \in \mathbb{R}_+$"Virtual" energy withdrawn by a storage AC component from the grid by technology $y$ at time step $t$ in zone $z$ - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{VS}^{stor}$ [MWh]
$\Gamma^{CRM}_{y,z,t} \in \mathbb{R}_+$Total "virtual" state of charge being held in reserves for technology $y$ at time step $t$ in zone $z$ - only applicable for standalone storage and co-located VRE and storage resources with activated capacity reserve margin policies, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh]

Parameters


NotationDescription
$D_{z,t}$Electricity demand in zone $z$ and at time step $t$ [MWh]
$\tau^{period}$number of time steps in each representative period $w \in \mathcal{W}^{rep}$ and each input period $w \in \mathcal{W}^{input}$
$\omega_{t}$weight of each model time step $\omega_t =1 \forall t \in T$ when modeling each time step of the year at an hourly resolution [1/year]
$n_s^{slope}$Cost of non-served energy/demand curtailment for price-responsive demand segment $s$ [$/MWh]
$n_s^{size}$Size of price-responsive demand segment $s$ as a fraction of the hourly zonal demand [%]
$\overline{\Omega}_{y,z}$Maximum capacity of technology $y$ in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the maximum grid connection capacity in MW AC)
$\underline{\Omega}_{y,z}$Minimum capacity of technology $y$ in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the minimum grid connection capacity in MW AC)
$\overline{\Omega}^{energy}_{y,z}$Maximum energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the maximum storage component in MWh)
$\underline{\Omega}^{energy}_{y,z}$Minimum energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the minimum storage component in MWh)
$\overline{\Omega}^{charge}_{y,z}$Maximum charging power capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\underline{\Omega}^{charge}_{y,z}$Minimum charging capacity of technology $y$ in zone $z$- only applicable for storage resources, $y \in \mathcal{O}^{asym}$ [MW]
$\overline{\Omega}^{pv}_{y,z}$Maximum solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\underline{\Omega}^{pv}_{y,z}$Minimum solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\overline{\Omega}^{wind}_{y,z}$Maximum wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\underline{\Omega}^{wind}_{y,z}$Minimum wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\overline{\Omega}^{inv}_{y,z}$Maximum inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\underline{\Omega}^{inv}_{y,z}$Minimum inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\overline{\Omega}^{dc,dis}_{y,z}$Maximum storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\underline{\Omega}^{dc,dis}_{y,z}$Minimum storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\overline{\Omega}^{dc,cha}_{y,z}$Maximum storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\underline{\Omega}^{dc,cha}_{y,z}$Minimum storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\overline{\Omega}^{ac,dis}_{y,z}$Maximum storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\underline{\Omega}^{ac,dis}_{y,z}$Minimum storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\overline{\Omega}^{ac,cha}_{y,z}$Maximum storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\underline{\Omega}^{ac,cha}_{y,z}$Minimum storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [MW AC]
$\overline{\Delta}_{y,z}$Existing installed capacity of technology $y$ in zone $z$ [MW] (Note that for co-located VRE and storage resources, this value represents the existing installed capacity of the grid connection in [MW AC])
$\overline{\Delta^{energy}_{y,z}}$Existing installed energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [MWh] (Note that for co-located VRE and storage resources, this value represents the existing installed energy capacity of the storage component in MWh)
$\overline{\Delta^{charge}_{y,z}}$Existing installed charging capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}$ [MW]
$\overline{\Delta^{pv}_{y,z}}$Existing installed solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [MW DC]
$\overline{\Delta^{wind}_{y,z}}$Existing installed wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [MW AC]
$\overline{\Delta^{inv}_{y,z}}$Existing installed inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [MW AC]
$\overline{\Delta^{dc,dis}_{y,z}}$Existing installed storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [MW DC]
$\overline{\Delta^{dc,cha}_{y,z}}$Existing installed storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW DC]
$\overline{\Delta^{ac,dis}_{y,z}}$Existing installed storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [MW AC]
$\overline{\Delta^{dc,cha}_{y,z}}$Existing installed storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [MW AC]
$\overline{\Omega}_{y,z}^{size}$Unit size of technology $y$ in zone $z$ [MW]
$\pi_{y,z}^{INVEST}$Investment cost (annual amortization of total construction cost) for power capacity of technology $y$ in zone $z$ [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the grid connection capacity in $/MW AC-yr)
$\pi_{y,z}^{INVEST,energy}$Investment cost (annual amortization of total construction cost) for energy capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{pv}$ [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the energy capacity of the storage component in $/MWh-yr)
$\pi_{y,z}^{INVEST,charge}$Investment cost (annual amortization of total construction cost) for charging power capacity of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}$ [$/MW-yr]
$\pi_{y,z}^{INVEST,pv}$Investment cost (annual amortization of total construction cost) for solar PV capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [$/MW DC-yr]
$\pi_{y,z}^{INVEST,wind}$Investment cost (annual amortization of total construction cost) for wind capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [$/MW AC-yr]
$\pi_{y,z}^{INVEST,inv}$Investment cost (annual amortization of total construction cost) for inverter capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [$/MW AC-yr]
$\pi_{y,z}^{INVEST,dc,dis}$Investment cost (annual amortization of total construction cost) for storage DC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [$/MW DC-yr]
$\pi_{y,z}^{INVEST,dc,cha}$Investment cost (annual amortization of total construction cost) for storage DC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [$/MW DC-yr]
$\pi_{y,z}^{INVEST,ac,dis}$Investment cost (annual amortization of total construction cost) for storage AC discharge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [$/MW AC-yr]
$\pi_{y,z}^{INVEST,ac,cha}$Investment cost (annual amortization of total construction cost) for storage AC charge capacity of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM}$Fixed O&M cost of technology $y$ in zone $z$ [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the grid connection capacity in $/MW AC-yr)
$\pi_{y,z}^{FOM,energy}$Fixed O&M cost of energy component of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O} \cup y \in \mathcal{VS}^{stor}$ [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the storage energy capacity in $/MWh-yr)
$\pi_{y,z}^{FOM,charge}$Fixed O&M cost of charging power component of technology $y$ in zone $z$ - only applicable for storage resources, $y \in \mathcal{O}$ [$/MW-yr]
$\pi_{y,z}^{FOM,pv}$Fixed O&M cost of the solar PV component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [$/MW DC-yr]
$\pi_{y,z}^{FOM,wind}$Fixed O&M cost of the wind component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM,inv}$Fixed O&M cost of the inverter component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an inverter component, $y \in \mathcal{VS}^{inv}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM,dc,dis}$Fixed O&M cost of the storage DC discharge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, $y \in \mathcal{VS}^{asym,dc,dis}$ [$/MW DC-yr]
$\pi_{y,z}^{FOM,dc,cha}$Fixed O&M cost of the storage DC charge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, $y \in \mathcal{VS}^{asym,dc,cha}$ [$/MW DC-yr]
$\pi_{y,z}^{FOM,ac,dis}$Fixed O&M cost of the storage AC discharge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, $y \in \mathcal{VS}^{asym,ac,dis}$ [$/MW AC-yr]
$\pi_{y,z}^{FOM,ac,cha}$Fixed O&M cost of the storage AC charge component of technology $y$ in zone $z$ - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, $y \in \mathcal{VS}^{asym,ac,cha}$ [$/MW AC-yr]
$\pi_{y,z}^{VOM}$Variable O&M cost of technology $y$ in zone $z$ [$/MWh]
$\pi_{y,z}^{VOM,charge}$Variable O&M cost of charging technology $y$ in zone $z$ - only applicable for storage and demand flexibility resources, $y \in \mathcal{O} \cup \mathcal{DF}$ [$/MWh]
$\pi_{y,z}^{VOM,pv}$Variable O&M cost of the solar PV component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a solar PV component, $y \in \mathcal{VS}^{pv}$ [$/MWh]
$\pi_{y,z}^{VOM,wind}$Variable O&M cost of the wind component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a wind component, $y \in \mathcal{VS}^{wind}$ [$/MWh]
$\pi_{y,z}^{VOM,dc,dis}$Variable O&M cost of the storage DC discharge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage DC discharge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,dis}$ [$/MWh]
$\pi_{y,z}^{VOM,dc,cha}$Variable O&M cost of the storage DC charge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage DC charge component, $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{asym,dc,cha}$ [$/MWh]
$\pi_{y,z}^{VOM,ac,dis}$Variable O&M cost of the storage AC discharge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage AC discharge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,dis}$ [$/MWh]
$\pi_{y,z}^{VOM,ac,cha}$Variable O&M cost of the storage AC charge component of technology $y$ in zone $z$ - only applicable to co-located VRE and storage resources with a storage AC charge component, $y \in \mathcal{VS}^{sym,ac} \cup y \in \mathcal{VS}^{asym,ac,cha}$ [$/MWh]
$\pi_{y,z}^{FUEL}$Fuel cost of technology $y$ in zone $z$ [$/MWh]
$\pi_{y,z}^{START}$Startup cost of technology $y$ in zone $z$ [$/startup]
$\upsilon^{reg}_{y,z}$Maximum fraction of capacity that a resource $y$ in zone $z$ can contribute to frequency regulation reserve requirements
$\upsilon^{rsv}_{y,z}$Maximum fraction of capacity that a resource $y$ in zone $z$ can contribute to upward operating (spinning) reserve requirements
$\pi^{Unmet}_{rsv}$Cost of unmet spinning reserves in [$/MW]
$\epsilon^{demand}_{reg}$Frequency regulation reserve requirement as a fraction of forecasted demand in each time step
$\epsilon^{vre}_{reg}$Frequency regulation reserve requirement as a fraction of variable renewable energy generation in each time step
$\epsilon^{demand}_{rsv}$Operating (spinning) reserve requirement as a fraction of forecasted demand in each time step
$\epsilon^{vre}_{rsv}$Operating (spinning) reserve requirement as a fraction of forecasted variable renewable energy generation in each time step
$\epsilon_{y,z}^{CO_2}$CO$_2$ emissions per unit energy produced by technology $y$ in zone $z$ [metric tons/MWh]
$\epsilon_{y,z,p}^{MinTech}$Equals to 1 if a generator of technology $y$ in zone $z$ is eligible for minimum capacity carveout policy $p \in \mathcal{P}^{MinTech}$, otherwise 0
$REQ_p^{MinTech}$The minimum capacity requirement of minimum capacity carveout policy $p \in \mathcal{P}^{MinTech}$ [MW]
$REQ_p^{MaxTech}$The maximum capacity requirement of minimum capacity carveout policy $p \in \mathcal{P}^{MinTech}$ [MW]
$\epsilon_{y,z,p}^{CRM}$Capacity derating factor of technology $y$ in zone $z$ for capacity reserve margin policy $p \in \mathcal{P}^{CRM}$ [fraction]
$RM_{z,p}^{CRM}$Reserve margin of zone $z$ of capacity reserve margin policy $p \in \mathcal{P}^{CRM}$ [fraction]
$\epsilon_{z,p,mass}^{CO_2}$Emission budget of zone $z$ under the emission cap $p \in \mathcal{P}^{CO_2}_{mass}$ [ million of metric tonnes]
$\epsilon_{z,p,demand}^{CO_2}$Maximum carbon intensity of the demand of zone $z$ under the emission cap $p \in \mathcal{P}^{CO_2}_{demand}$ [metric tonnes/MWh]
$\epsilon_{z,p,gen}^{CO_2}$Maximum emission rate of the generation of zone $z$ under the emission cap $p \in \mathcal{P}^{CO_2}_{gen}$ [metric tonnes/MWh]
$\rho_{y,z}^{min}$Minimum stable power output per unit of installed capacity for technology $y$ in zone $z$ [%]
$\rho_{y,z,t}^{max}$Maximum available generation per unit of installed capacity during time step t for technology y in zone z [%]
$\rho_{y,z,t}^{max,pv}$Maximum available generation per unit of installed capacity for the solar PV component of a co-located VRE and storage resource during time step t for technology y in zone z [%]
$\rho_{y,z,t}^{max,wind}$Maximum available generation per unit of installed capacity for the wind component of a co-located VRE and storage resource during time step t for technology y in zone z [%]
$VREIndex_{y,z}$Resource bin index for VRE technology $y$ in zone $z$. $VREIndex_{y,z}=1$ for the first bin, and $VREIndex_{y,z}=0$ for remaining bins. Only defined for $y\in \mathcal{VRE}$
$\varphi^{map}_{l,z}$Topology of the network, for line l: $\varphi^{map}_{l,z}=1$ for start zone $z$, - 1 for end zone $z$, 0 otherwise.
$\mathcal{B}_{l}$DC-OPF coefficient for line $l$ [MWh]
$\Delta \theta^{\max}_{l}$Maximum voltage phase angle difference for line $l$ [radian]
$\eta_{y,z}^{loss}$Self discharge rate per time step per unit of installed capacity for storage technology $y$ in zone $z$ [%]
$\eta_{y,z}^{charge}$Single-trip efficiency of storage charging/demand deferral for technology $y$ in zone $z$ [%]
$\eta_{y,z}^{discharge}$Single-trip efficiency of storage (and hydro reservoir) discharging/demand satisfaction for technology $y$ in zone $z$ [%]
$\eta_{y,z}^{charge,dc}$Single-trip efficiency of storage DC charging/demand deferral for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{discharge,dc}$Single-trip efficiency of storage DC discharging/demand satisfaction for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{charge,ac}$Single-trip efficiency of storage AC charging/demand deferral for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{discharge,ac}$Single-trip efficiency of storage AC discharging/demand satisfaction for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{inverter}$Inverter efficiency representing losses from converting DC to AC power and vice versa for technology $y$ in zone $z$ for co-located VRE and storage resources [%]
$\eta_{y,z}^{ILR,pv}$Inverter loading ratio (the solar PV capacity sizing to the inverter capacity built) of technology $y$ in zone $z$ for co-located VRE and storage resources with a solar PV component [%]
$\eta_{y,z}^{ILR,wind}$Inverter loading ratio (the wind PV capacity sizing to the grid connection capacity built) of technology $y$ in zone $z$ for co-located VRE and storage resources with a wind component [%]
$\mu_{y,z}^{stor}$Ratio of energy capacity to discharge power capacity for storage technology (and hydro reservoir) $y$ in zone $z$ [MWh/MW]
$\mu_{y,z}^{dc,stor}$Ratio of discharge power capacity to energy capacity for the storage DC component of co-located VRE and storage technology $y$ in zone $z$ [MW/MWh]
$\mu_{y,z}^{ac,stor}$Ratio of discharge power capacity to energy capacity for the storage AC component of co-located VRE and storage technology $y$ in zone $z$ [MW/MWh]
$\mu_{y,z}^{\mathcal{DF}}$Maximum percentage of hourly demand that can be shifted by technology $y$ in zone $z$ [%]
$\kappa_{y,z}^{up}$Maximum ramp-up rate per time step as percentage of installed capacity of technology y in zone z [%/hr]
$\kappa_{y,z}^{down}$Maximum ramp-down rate per time step as percentage of installed capacity of technology y in zone z [%/hr]
$\tau_{y,z}^{up}$Minimum uptime for thermal generator type y in zone z before new shutdown [hours].
$\tau_{y,z}^{down}$Minimum downtime or thermal generator type y in zone z before new restart [hours].
$\tau_{y,z}^{advance}$maximum time by which flexible demand resource can be advanced [hours]
$\tau_{y,z}^{delay}$maximum time by which flexible demand resource can be delayed [hours]
$\eta_{y,z}^{dflex}$energy losses associated with shifting the flexible demand [%]
$\mu_{p,z}^{\mathcal{ESR}}$share of total demand in each model zone $z \in \mathcal{ESR}^{p}$ that must be served by qualifying renewable energy resources $y \in \mathcal{G}^{ESR}_{p}$
$f(n)$Mapping each modeled period $n \in \mathcal{N}$ to corresponding representative period $w \in \mathcal{W}$
$\eta_{y}^{electrolyzer}$Efficiency of the electrolyzer $y$ in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced [MWh/t] (optional parameter)
$ $^{hydrogen}_y$Price of hydrogen per metric tonne for electrolyzer $y$ [$/t] (optional parameter)
$\mathcal{Min kt}_y$Minimum annual quantity of hydrogen that must be produced by electrolyzer $y$ in kilotonnes [kt] (optional parameter)

diff --git a/previews/PR655/Model_Concept_Overview/objective_function/index.html b/previews/PR655/Model_Concept_Overview/objective_function/index.html index 2d23a078e1..ebb0c6b46a 100644 --- a/previews/PR655/Model_Concept_Overview/objective_function/index.html +++ b/previews/PR655/Model_Concept_Overview/objective_function/index.html @@ -28,4 +28,4 @@ & \sum_{y \in \mathcal{VS}^{sym,dc} \cup \mathcal{VS}^{asym,dc,cha}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} \left( \omega_{t}\times\pi^{VOM,dc,cha}_{y,z} \times \frac{\Pi^{dc}_{y,z,t}}{\eta^{inverter}_{y,z}}\right) + \\ & \sum_{y \in \mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,dis}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} \left( \omega_{t}\times\pi^{VOM,ac,dis}_{y,z} \times \Theta^{ac}_{y,z,t}\right) + \\ & \sum_{y \in \mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,cha}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} \left( \omega_{t}\times\pi^{VOM,ac,cha}_{y,z} \times \Pi^{ac}_{y,z,t}\right) -\end{aligned}\]

The first summation represents the fixed costs of generation/discharge over all zones and technologies, which reflects the sum of the annualized capital cost, $\pi^{INVEST}_{y,z}$, times the total new capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM}_{y,z}$, times the net installed generation capacity, $\overline{\Omega}^{size}_{y,z} \times \Delta^{total}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources ($y \in \mathcal{O} \cup \mathcal{VS}^{stor}$). This term includes the sum of the annualized energy capital cost, $\pi^{INVEST,energy}_{y,z}$, times the total new energy capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, energy}_{y,z}$, times the net installed energy storage capacity, $\Delta^{total}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components ($y \in \mathcal{O}^{asym}$). This term includes the sum of the annualized charging power capital cost, $\pi^{INVEST,charge}_{y,z}$, times the total new charging power capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, energy}_{y,z}$, times the net installed charging power capacity, $\Delta^{total}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The fourth and fifth summations correspond to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, $\pi^{FUEL}_{y,z}$ (if any), plus variable O&M cost, $\pi^{VOM}_{y,z}$ times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, $y\in\mathcal{DF}$) in time step $t$, $\Theta_{y,z,t}$, and the weight of each time step $t$, $\omega_t$. The fifth summation represents the variable charging O&M cost, $\pi^{VOM,charge}_{y,z}$ times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step $t$ , $\Pi_{y,z,t}$ and the annual weight of time step $t$,$\omega_t$. The weight of each time step, $\omega_t$, is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, $t$ such that the sum of $\omega_t \forall t \in T = 8760$, approximating annual operating costs.

The sixth summation represents the total cost of unserved demand across all segments $s$ of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), $n_{s}^{slope}$, times the amount of non-served energy, $\Lambda_{y,z,t}$, for each segment on each zone during each time step (weighted by $\omega_t$).

The seventh summation represents the total cost of not meeting hourly operating reserve requirements (if modeled), where $\pi^{unmet}_{rsv}$ is the cost penalty per unit of non-served reserve requirement, and $r^{unmet}_t$ is the amount of non-served reserve requirement in each time step (weighted by $\omega_t$).

The eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. $y \in \mathcal{UC}$), equal to the cost of start-up, $\pi^{START}_{y,z}$, times the number of startup events, $\chi_{y,z,t}$, for the cluster of units in each zone and time step (weighted by $\omega_t$).

The ninth term corresponds to the transmission reinforcement or construction costs, for each transmission line (if modeled). Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, $pi^{TCAP}_{l}$, times the additional transmission capacity variable, $\bigtriangleup\varphi^{max}_{l}$. Note that fixed O&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.

The tenth term onwards specifically relates to the breakdown investment, fixed O&M, and variable O&M costs associated with each configurable component of a co-located VRE and storage resource. The tenth term represents to the fixed cost of installed inverter capacity and is summed over only the co-located resources with an inverter component ($y \in \mathcal{VS}^{inv}$). This term includes the sum of the annualized inverter capital cost, $\pi^{INVEST,inv}_{y,z}$, times the total new inverter capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, inv}_{y,z}$, times the net installed inverter capacity, $\Delta^{total,inv}_{y,z}$ (e.g., existing capacity less retirements plus additions). The eleventh term represents the fixed cost of installed solar PV capacity and is summed over only the co-located resources with a solar PV component ($y \in \mathcal{VS}^{pv}$). This term includes the sum of the annualized solar PV capital cost, $\pi^{INVEST,pv}_{y,z}$, times the total new solar PV capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, pv}_{y,z}$, times the net installed solar PV capacity, $\Delta^{total,pv}_{y,z}$ (e.g., existing capacity less retirements plus additions). The twelveth term represents the fixed cost of installed wind capacity and is summed over only the co-located resources with a wind component ($y \in \mathcal{VS}^{wind}$). This term includes the sum of the annualized wind capital cost, $\pi^{INVEST,wind}_{y,z}$, times the total new wind capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, wind}_{y,z}$, times the net installed wind capacity, $\Delta^{total,wind}_{y,z}$ (e.g., existing capacity less retirements plus additions). The thirteenth term represents the fixed cost of installed storage DC discharge capacity and is summed over only the co-located resources with an asymmetric storage DC discharge component ($y \in \mathcal{VS}^{asym,dc,dis}$). This term includes the sum of the annualized storage DC discharge capital cost, $\pi^{INVEST,dc,dis}_{y,z}$, times the total new storage DC discharge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, dc, dis}_{y,z}$, times the net installed storage DC discharge capacity, $\Delta^{total,dc,dis}_{y,z}$ (e.g., existing capacity less retirements plus additions). The fourteenth term represents the fixed cost of installed storage DC charge capacity and is summed over only the co-located resources with an asymmetric storage DC charge component ($y \in \mathcal{VS}^{asym,dc,cha}$). This term includes the sum of the annualized storage DC charge capital cost, $\pi^{INVEST,dc,cha}_{y,z}$, times the total new storage DC charge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, dc, cha}_{y,z}$, times the net installed storage DC charge capacity, $\Delta^{total,dc,cha}_{y,z}$ (e.g., existing capacity less retirements plus additions). The fifteenth term represents the fixed cost of installed storage AC discharge capacity and is summed over only the co-located resources with an asymmetric storage AC discharge component ($y \in \mathcal{VS}^{asym,ac,dis}$). This term includes the sum of the annualized storage AC discharge capital cost, $\pi^{INVEST,ac,dis}_{y,z}$, times the total new storage AC discharge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, ac, dis}_{y,z}$, times the net installed storage AC discharge capacity, $\Delta^{total,ac,dis}_{y,z}$ (e.g., existing capacity less retirements plus additions). The sixteenth term represents to the fixed cost of installed storage AC charge capacity and is summed over only the co-located resources with an asymmetric storage AC charge component ($y \in \mathcal{VS}^{asym,ac,cha}$). This term includes the sum of the annualized storage AC charge capital cost, $\pi^{INVEST,ac,cha}_{y,z}$, times the total new storage AC charge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, ac, cha}_{y,z}$, times the net installed storage AC charge capacity, $\Delta^{total,ac,cha}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The seventeeth term onwards corresponds to the operational cost across all zones, technologies, and time steps for co-located VRE and storage resources. The seventeenth summation represents the variable O&M cost, $\pi^{VOM,pv}_{y,z}$, times the energy generation by solar PV resources ($y\in\mathcal{VS}^{pv}$) in time step $t$, $\Theta^{pv}_{y,z,t}$, the inverter efficiency, $\eta^{inverter}_{y,z}$, and the weight of each time step $t$, $\omega_t$. The eighteenth summation represents the variable O&M cost, $\pi^{VOM,wind}_{y,z}$, times the energy generation by wind resources ($y\in\mathcal{VS}^{wind}$) in time step $t$, $\Theta^{wind}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$. The nineteenth summation represents the variable O&M cost, $\pi^{VOM,dc,dis}_{y,z}$, times the energy discharge by storage DC components ($y\in\mathcal{VS}^{sym,dc} \cup \mathcal{VS}^{asym,dc,dis}$) in time step $t$, $\Theta^{dc}_{y,z,t}$, the inverter efficiency, $\eta^{inverter}_{y,z}$, and the weight of each time step $t$, $\omega_t$. The twentieth summation represents the variable O&M cost, $\pi^{VOM,dc,cha}_{y,z}$, times the energy withdrawn by storage DC components ($y\in\mathcal{VS}^{sym,dc} \cup \mathcal{VS}^{asym,dc,cha}$) in time step $t$, $\Pi^{dc}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$, and divided by the inverter efficiency, $\eta^{inverter}_{y,z}$. The twenty-first summation represents the variable O&M cost, $\pi^{VOM,ac,dis}_{y,z}$, times the energy discharge by storage AC components ($y\in\mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,dis}$) in time step $t$, $\Theta^{ac}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$. The twenty-second summation represents the variable O&M cost, $\pi^{VOM,ac,cha}_{y,z}$, times the energy withdrawn by storage AC components ($y\in\mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,cha}$) in time step $t$, $\Pi^{ac}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$.

In summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions:

  1. where and how to invest on capacity,
  2. how to dispatch or operate that capacity,
  3. which consumer demand segments to serve or curtail,
  4. how to cycle and commit thermal units subject to unit commitment decisions,
  5. and where and how to invest in additional transmission network capacity to increase power transfer capacity between zones.

Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.

While the objective function is formulated as a cost minimization problem, it is also equivalent to a social welfare maximization problem, with the bulk of demand treated as inelastic and always served, and the utility of consumption for price-elastic consumers represented as a segment-wise approximation, as per the cost of unserved demand summation above.

+\end{aligned}\]

The first summation represents the fixed costs of generation/discharge over all zones and technologies, which reflects the sum of the annualized capital cost, $\pi^{INVEST}_{y,z}$, times the total new capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM}_{y,z}$, times the net installed generation capacity, $\overline{\Omega}^{size}_{y,z} \times \Delta^{total}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources ($y \in \mathcal{O} \cup \mathcal{VS}^{stor}$). This term includes the sum of the annualized energy capital cost, $\pi^{INVEST,energy}_{y,z}$, times the total new energy capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, energy}_{y,z}$, times the net installed energy storage capacity, $\Delta^{total}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components ($y \in \mathcal{O}^{asym}$). This term includes the sum of the annualized charging power capital cost, $\pi^{INVEST,charge}_{y,z}$, times the total new charging power capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, energy}_{y,z}$, times the net installed charging power capacity, $\Delta^{total}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The fourth and fifth summations correspond to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, $\pi^{FUEL}_{y,z}$ (if any), plus variable O&M cost, $\pi^{VOM}_{y,z}$ times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, $y\in\mathcal{DF}$) in time step $t$, $\Theta_{y,z,t}$, and the weight of each time step $t$, $\omega_t$. The fifth summation represents the variable charging O&M cost, $\pi^{VOM,charge}_{y,z}$ times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step $t$ , $\Pi_{y,z,t}$ and the annual weight of time step $t$,$\omega_t$. The weight of each time step, $\omega_t$, is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, $t$ such that the sum of $\omega_t \forall t \in T = 8760$, approximating annual operating costs.

The sixth summation represents the total cost of unserved demand across all segments $s$ of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), $n_{s}^{slope}$, times the amount of non-served energy, $\Lambda_{y,z,t}$, for each segment on each zone during each time step (weighted by $\omega_t$).

The seventh summation represents the total cost of not meeting hourly operating reserve requirements (if modeled), where $\pi^{unmet}_{rsv}$ is the cost penalty per unit of non-served reserve requirement, and $r^{unmet}_t$ is the amount of non-served reserve requirement in each time step (weighted by $\omega_t$).

The eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. $y \in \mathcal{UC}$), equal to the cost of start-up, $\pi^{START}_{y,z}$, times the number of startup events, $\chi_{y,z,t}$, for the cluster of units in each zone and time step (weighted by $\omega_t$).

The ninth term corresponds to the transmission reinforcement or construction costs, for each transmission line (if modeled). Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, $pi^{TCAP}_{l}$, times the additional transmission capacity variable, $\bigtriangleup\varphi^{max}_{l}$. Note that fixed O&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.

The tenth term onwards specifically relates to the breakdown investment, fixed O&M, and variable O&M costs associated with each configurable component of a co-located VRE and storage resource. The tenth term represents to the fixed cost of installed inverter capacity and is summed over only the co-located resources with an inverter component ($y \in \mathcal{VS}^{inv}$). This term includes the sum of the annualized inverter capital cost, $\pi^{INVEST,inv}_{y,z}$, times the total new inverter capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, inv}_{y,z}$, times the net installed inverter capacity, $\Delta^{total,inv}_{y,z}$ (e.g., existing capacity less retirements plus additions). The eleventh term represents the fixed cost of installed solar PV capacity and is summed over only the co-located resources with a solar PV component ($y \in \mathcal{VS}^{pv}$). This term includes the sum of the annualized solar PV capital cost, $\pi^{INVEST,pv}_{y,z}$, times the total new solar PV capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, pv}_{y,z}$, times the net installed solar PV capacity, $\Delta^{total,pv}_{y,z}$ (e.g., existing capacity less retirements plus additions). The twelveth term represents the fixed cost of installed wind capacity and is summed over only the co-located resources with a wind component ($y \in \mathcal{VS}^{wind}$). This term includes the sum of the annualized wind capital cost, $\pi^{INVEST,wind}_{y,z}$, times the total new wind capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, wind}_{y,z}$, times the net installed wind capacity, $\Delta^{total,wind}_{y,z}$ (e.g., existing capacity less retirements plus additions). The thirteenth term represents the fixed cost of installed storage DC discharge capacity and is summed over only the co-located resources with an asymmetric storage DC discharge component ($y \in \mathcal{VS}^{asym,dc,dis}$). This term includes the sum of the annualized storage DC discharge capital cost, $\pi^{INVEST,dc,dis}_{y,z}$, times the total new storage DC discharge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, dc, dis}_{y,z}$, times the net installed storage DC discharge capacity, $\Delta^{total,dc,dis}_{y,z}$ (e.g., existing capacity less retirements plus additions). The fourteenth term represents the fixed cost of installed storage DC charge capacity and is summed over only the co-located resources with an asymmetric storage DC charge component ($y \in \mathcal{VS}^{asym,dc,cha}$). This term includes the sum of the annualized storage DC charge capital cost, $\pi^{INVEST,dc,cha}_{y,z}$, times the total new storage DC charge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, dc, cha}_{y,z}$, times the net installed storage DC charge capacity, $\Delta^{total,dc,cha}_{y,z}$ (e.g., existing capacity less retirements plus additions). The fifteenth term represents the fixed cost of installed storage AC discharge capacity and is summed over only the co-located resources with an asymmetric storage AC discharge component ($y \in \mathcal{VS}^{asym,ac,dis}$). This term includes the sum of the annualized storage AC discharge capital cost, $\pi^{INVEST,ac,dis}_{y,z}$, times the total new storage AC discharge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, ac, dis}_{y,z}$, times the net installed storage AC discharge capacity, $\Delta^{total,ac,dis}_{y,z}$ (e.g., existing capacity less retirements plus additions). The sixteenth term represents to the fixed cost of installed storage AC charge capacity and is summed over only the co-located resources with an asymmetric storage AC charge component ($y \in \mathcal{VS}^{asym,ac,cha}$). This term includes the sum of the annualized storage AC charge capital cost, $\pi^{INVEST,ac,cha}_{y,z}$, times the total new storage AC charge capacity added (if any), plus the Fixed O&M cost, $\pi^{FOM, ac, cha}_{y,z}$, times the net installed storage AC charge capacity, $\Delta^{total,ac,cha}_{y,z}$ (e.g., existing capacity less retirements plus additions).

The seventeeth term onwards corresponds to the operational cost across all zones, technologies, and time steps for co-located VRE and storage resources. The seventeenth summation represents the variable O&M cost, $\pi^{VOM,pv}_{y,z}$, times the energy generation by solar PV resources ($y\in\mathcal{VS}^{pv}$) in time step $t$, $\Theta^{pv}_{y,z,t}$, the inverter efficiency, $\eta^{inverter}_{y,z}$, and the weight of each time step $t$, $\omega_t$. The eighteenth summation represents the variable O&M cost, $\pi^{VOM,wind}_{y,z}$, times the energy generation by wind resources ($y\in\mathcal{VS}^{wind}$) in time step $t$, $\Theta^{wind}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$. The nineteenth summation represents the variable O&M cost, $\pi^{VOM,dc,dis}_{y,z}$, times the energy discharge by storage DC components ($y\in\mathcal{VS}^{sym,dc} \cup \mathcal{VS}^{asym,dc,dis}$) in time step $t$, $\Theta^{dc}_{y,z,t}$, the inverter efficiency, $\eta^{inverter}_{y,z}$, and the weight of each time step $t$, $\omega_t$. The twentieth summation represents the variable O&M cost, $\pi^{VOM,dc,cha}_{y,z}$, times the energy withdrawn by storage DC components ($y\in\mathcal{VS}^{sym,dc} \cup \mathcal{VS}^{asym,dc,cha}$) in time step $t$, $\Pi^{dc}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$, and divided by the inverter efficiency, $\eta^{inverter}_{y,z}$. The twenty-first summation represents the variable O&M cost, $\pi^{VOM,ac,dis}_{y,z}$, times the energy discharge by storage AC components ($y\in\mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,dis}$) in time step $t$, $\Theta^{ac}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$. The twenty-second summation represents the variable O&M cost, $\pi^{VOM,ac,cha}_{y,z}$, times the energy withdrawn by storage AC components ($y\in\mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,cha}$) in time step $t$, $\Pi^{ac}_{y,z,t}$, and the weight of each time step $t$, $\omega_t$.

In summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions:

  1. where and how to invest on capacity,
  2. how to dispatch or operate that capacity,
  3. which consumer demand segments to serve or curtail,
  4. how to cycle and commit thermal units subject to unit commitment decisions,
  5. and where and how to invest in additional transmission network capacity to increase power transfer capacity between zones.

Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.

While the objective function is formulated as a cost minimization problem, it is also equivalent to a social welfare maximization problem, with the bulk of demand treated as inelastic and always served, and the utility of consumption for price-elastic consumers represented as a segment-wise approximation, as per the cost of unserved demand summation above.

diff --git a/previews/PR655/Model_Concept_Overview/power_balance/index.html b/previews/PR655/Model_Concept_Overview/power_balance/index.html index e7b6b6cda5..e191b7282a 100644 --- a/previews/PR655/Model_Concept_Overview/power_balance/index.html +++ b/previews/PR655/Model_Concept_Overview/power_balance/index.html @@ -4,4 +4,4 @@ & \sum_{y\in \mathcal{DF}}{(-\Theta_{y,z,t}+\Pi_{y,z,t})} +\sum_{y\in \mathcal{W}}{\Theta_{y,z,t}}+ \sum_{y\in \mathcal{VS}}{\Theta_{y,z,t}} - \sum_{y\in \mathcal{VS}^{stor}}{\Pi_{y,z,t}} + \\ & \sum_{s\in \mathcal{S}}{\Lambda_{s,z,t}} - \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \Phi_{l,t})} -\frac{1}{2} \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \beta_{l,t}(\cdot))} = D_{z,t} \quad \quad \forall z\in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

+\end{aligned}\]

diff --git a/previews/PR655/Model_Reference/Multi_Stage/configure_multi_stage_inputs/index.html b/previews/PR655/Model_Reference/Multi_Stage/configure_multi_stage_inputs/index.html index 0ed2f34874..e54b13df3e 100644 --- a/previews/PR655/Model_Reference/Multi_Stage/configure_multi_stage_inputs/index.html +++ b/previews/PR655/Model_Reference/Multi_Stage/configure_multi_stage_inputs/index.html @@ -1,4 +1,4 @@ Configure multi-stage inputs · GenX

Configure multi stage inputs

GenX.compute_overnight_capital_costMethod
function compute_overnight_capital_cost(settings_d::Dict,inv_costs_yr::Array,crp::Array,tech_wacc::Array)

This function computes overnight capital costs incured within the model horizon, assuming that annualized costs to be paid after the model horizon are fully recoverable, and so are not included in the cost computation.

For each resource $y \in \mathcal{G}$ with annualized investment cost $AIC_{y}$ and capital recovery period $CRP_{y}$, overnight capital costs $OCC_{y}$ are computed as follows:

\[\begin{aligned} & OCC_{y} = \sum^{min(CRP_{y},H)}_{i=1}\frac{AIC_{y}}{(1+WACC_{y})^{i}} -\end{aligned}\]

where $WACC_y$ is the technology-specific weighted average cost of capital (set by the "WACC" field in the Generators_data.csv or Network.csv files), $H$ is the number of years remaining between the start of the current model stage and the model horizon (the end of the final model stage) and $CRP_y$ is the capital recovery period for technology $y$ (specified in Generators_data.csv).

inputs:

  • settings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • inv_costs_yr - array object containing annualized investment costs.
  • crp - array object of capital recovery period values.
  • tech_wacc - array object containing technology-specific weighted costs of capital.

NOTE: The inv_costs_yr and crp arrays must be the same length; values with the same index in each array correspond to the same resource $y \in \mathcal{G}$.

returns: array object containing overnight capital costs, the discounted sum of annual investment costs incured within the model horizon.

source
GenX.configure_multi_stage_inputsMethod
function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)

This function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:

  1. Overnight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.

  2. Annualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by "StageLength" field in multi_stage_settings.yml).

  3. Internal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.

  4. When NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the "Line_Max_Flow_Possible_MW" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.

inputs:

  • inputs_d - dict object containing model inputs dictionary generated by load_inputs().
  • settings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • NetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the "NetworkExpansion" field in genx_settings.yml.

returns: dictionary containing updated model inputs, to be used in the generate_model() method.

source
+\end{aligned}\]

where $WACC_y$ is the technology-specific weighted average cost of capital (set by the "WACC" field in the Generators_data.csv or Network.csv files), $H$ is the number of years remaining between the start of the current model stage and the model horizon (the end of the final model stage) and $CRP_y$ is the capital recovery period for technology $y$ (specified in Generators_data.csv).

inputs:

NOTE: The inv_costs_yr and crp arrays must be the same length; values with the same index in each array correspond to the same resource $y \in \mathcal{G}$.

returns: array object containing overnight capital costs, the discounted sum of annual investment costs incured within the model horizon.

source
GenX.configure_multi_stage_inputsMethod
function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)

This function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:

  1. Overnight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.

  2. Annualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by "StageLength" field in multi_stage_settings.yml).

  3. Internal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.

  4. When NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the "Line_Max_Flow_Possible_MW" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.

inputs:

  • inputs_d - dict object containing model inputs dictionary generated by load_inputs().
  • settings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • NetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the "NetworkExpansion" field in genx_settings.yml.

returns: dictionary containing updated model inputs, to be used in the generate_model() method.

source
diff --git a/previews/PR655/Model_Reference/Multi_Stage/dual_dynamic_programming/index.html b/previews/PR655/Model_Reference/Multi_Stage/dual_dynamic_programming/index.html index 152b9cc14a..0988fbdd74 100644 --- a/previews/PR655/Model_Reference/Multi_Stage/dual_dynamic_programming/index.html +++ b/previews/PR655/Model_Reference/Multi_Stage/dual_dynamic_programming/index.html @@ -1,12 +1,12 @@ -Model multi stage: Dual Dynamic Programming Algorithm · GenX

Dual Dynamic Programming Algorithm

GenX.add_cutMethod
add_cut(EP_cur::Model, EP_next::Model, start_cap_d::Dict, cap_track_d::Dict)

inputs:

  • EP_cur - JuMP model from the current model stage $p$.
  • EP_next - JuMP model from the next model stage $p+1$..
  • start_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.
  • cap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.

returns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.

source
GenX.configure_ddp_dictsMethod
configure_ddp_dicts(setup::Dict, inputs::Dict)

This function instantiates Dictionary objects containing the names of linking expressions, constraints, and variables used in multi-stage modeling.

inputs:

  • setup - Dictionary object containing GenX settings and key parameters.
  • inputs – Dictionary of inputs for each model period, generated by the load_inputs() method.

returns:

  • start_cap_d – Dictionary which contains linking expression names as keys and linking constraint names as values, used for setting the end capacity in stage $p$ to the starting capacity in stage $p+1$.
  • cap_track_d – Dictionary which contains linking variable names as keys and linking constraint names as values, used for enforcing endogenous retirements.
source
GenX.fix_capacity_trackingMethod
fix_capacity_tracking(EP_prev::Model, EP_cur::Model, cap_track_d::Dict, cur_stage::Int)

This function sets the right hand side values of the new and retired capacity tracking linking constraints in the current stage $p$ to the realized values of the new and retired capacity tracking linking variables from the previous stage $p-1$ as part of the forward pass. where tracking linking variables are defined variables for tracking, linking and passing realized expansion and retirement of capacities of each stage to the next stage. Tracking linking variables are each defined in endogenous_retirement_discharge, endogenous_retirement_energy, and endogenous_retirement_charge functions. Three examples are "vCAPTRACK", "vCAPTRACKCHARGE", and ""vCAPTRACKENERGY"

inputs:

  • EP_prev - JuMP model from the previous model stage $p-1$.
  • EP_cur - JuMP model from the current model stage $p$.
  • cap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.
  • cur_period – Int representing the current model stage $p$.

returns: JuMP model with updated linking constraints.

source
GenX.fix_initial_investmentsMethod
fix_initial_investments(EP_prev::Model, EP_cur::Model, start_cap_d::Dict)

This function sets the right hand side values of the existing capacity linking constraints in the current stage $p$ to the realized values of the total available end capacity linking variable expressions from the previous stage $p-1$ as part of the forward pass.

inputs:

  • EP_prev - JuMP model from the previous model stage $p-1$.
  • EP_cur - JuMP model from the current model stage $p$.
  • start_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.

returns: JuMP model with updated linking constraints.

source
GenX.generate_cut_component_invMethod
generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)

This function generates Bender's cut expressions for linking capacity investment variable expression in the form:

\[\begin{aligned} +Model multi stage: Dual Dynamic Programming Algorithm · GenX

Dual Dynamic Programming Algorithm

GenX.add_cutMethod
add_cut(EP_cur::Model, EP_next::Model, start_cap_d::Dict, cap_track_d::Dict)

inputs:

  • EP_cur - JuMP model from the current model stage $p$.
  • EP_next - JuMP model from the next model stage $p+1$..
  • start_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.
  • cap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.

returns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.

source
GenX.configure_ddp_dictsMethod
configure_ddp_dicts(setup::Dict, inputs::Dict)

This function instantiates Dictionary objects containing the names of linking expressions, constraints, and variables used in multi-stage modeling.

inputs:

  • setup - Dictionary object containing GenX settings and key parameters.
  • inputs – Dictionary of inputs for each model period, generated by the load_inputs() method.

returns:

  • start_cap_d – Dictionary which contains linking expression names as keys and linking constraint names as values, used for setting the end capacity in stage $p$ to the starting capacity in stage $p+1$.
  • cap_track_d – Dictionary which contains linking variable names as keys and linking constraint names as values, used for enforcing endogenous retirements.
source
GenX.fix_capacity_trackingMethod
fix_capacity_tracking(EP_prev::Model, EP_cur::Model, cap_track_d::Dict, cur_stage::Int)

This function sets the right hand side values of the new and retired capacity tracking linking constraints in the current stage $p$ to the realized values of the new and retired capacity tracking linking variables from the previous stage $p-1$ as part of the forward pass. where tracking linking variables are defined variables for tracking, linking and passing realized expansion and retirement of capacities of each stage to the next stage. Tracking linking variables are each defined in endogenous_retirement_discharge, endogenous_retirement_energy, and endogenous_retirement_charge functions. Three examples are "vCAPTRACK", "vCAPTRACKCHARGE", and ""vCAPTRACKENERGY"

inputs:

  • EP_prev - JuMP model from the previous model stage $p-1$.
  • EP_cur - JuMP model from the current model stage $p$.
  • cap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.
  • cur_period – Int representing the current model stage $p$.

returns: JuMP model with updated linking constraints.

source
GenX.fix_initial_investmentsMethod
fix_initial_investments(EP_prev::Model, EP_cur::Model, start_cap_d::Dict)

This function sets the right hand side values of the existing capacity linking constraints in the current stage $p$ to the realized values of the total available end capacity linking variable expressions from the previous stage $p-1$ as part of the forward pass.

inputs:

  • EP_prev - JuMP model from the previous model stage $p-1$.
  • EP_cur - JuMP model from the current model stage $p$.
  • start_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.

returns: JuMP model with updated linking constraints.

source
GenX.generate_cut_component_invMethod
generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)

This function generates Bender's cut expressions for linking capacity investment variable expression in the form:

\[\begin{aligned} \mu_{next}^{\top}(\hat{x}_{cur} - x_{cur}) -\end{aligned}\]

where $\mu_{next}$ is a vector of dual values of the linking constraints defined by constr_name in EP_next, $\hat{x}_{cur}$ is a vector of realized values from the forward pass of the linking capacity investment variable expressions expr_name from EP_cur, and $x_{cur}$ is a vector of unrealized linking capacity investment variable expressions from EP_cur. inputs:

inputs:

  • EP_cur - JuMP model from the current model stage $p$, solved in the forward pass.
  • EP_next - JuMP model from the next model stage $p+1$, solved in the forward pass.
  • expr_name – Symbol representing the name of a JuMP expression array which contains linking capacity investment variables.
  • constr_name – Symbol representing the name of the array of linking JuMP constraints which contain the linking capacity investment variables.

returns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.

source
GenX.generate_cut_component_trackMethod
generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)

This function generates Bender's cut expressions for total new or retired capacity tracking linking variables in the form:

\[\begin{aligned} +\end{aligned}\]

where $\mu_{next}$ is a vector of dual values of the linking constraints defined by constr_name in EP_next, $\hat{x}_{cur}$ is a vector of realized values from the forward pass of the linking capacity investment variable expressions expr_name from EP_cur, and $x_{cur}$ is a vector of unrealized linking capacity investment variable expressions from EP_cur. inputs:

inputs:

  • EP_cur - JuMP model from the current model stage $p$, solved in the forward pass.
  • EP_next - JuMP model from the next model stage $p+1$, solved in the forward pass.
  • expr_name – Symbol representing the name of a JuMP expression array which contains linking capacity investment variables.
  • constr_name – Symbol representing the name of the array of linking JuMP constraints which contain the linking capacity investment variables.

returns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.

source
GenX.generate_cut_component_trackMethod
generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)

This function generates Bender's cut expressions for total new or retired capacity tracking linking variables in the form:

\[\begin{aligned} \mu_{next}^{\top}(\hat{x}_{cur} - x_{cur}) -\end{aligned}\]

where $\mu_{next}$ is a vector of dual values of the linking constraints defined by constr_name in EP_next, $\hat{x}_{cur}$ is a vector of realized values from the forward pass of the new or retired capacity tracking linking variables var_name from EP_cur, and $x_{cur}$ is a vector of unrealized new or retired capacity tracking linking variables from EP_cur.

inputs:

  • EP_cur - JuMP model from the current model stage $p$.
  • EP_next - JuMP model from the next model stage $p+1$.
  • var_name – Symbol representing the name of a JuMP variable array which contains total new or retired capacity tracking linking variables.
  • constr_name – Symbol representing the name of the array of linking JuMP constraints which contain total new or retired capacity tracking linking variables.

returns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.

source
GenX.initialize_cost_to_goMethod
initialize_cost_to_go(settings_d::Dict, EP::Model)

This function scales the model objective function so that costs are consistent with multi-stage modeling and introduces a cost-to-go function variable to the objective function.

The updated objective function $OBJ^{*}$ returned by this method takes the form:

\[\begin{aligned} +\end{aligned}\]

where $\mu_{next}$ is a vector of dual values of the linking constraints defined by constr_name in EP_next, $\hat{x}_{cur}$ is a vector of realized values from the forward pass of the new or retired capacity tracking linking variables var_name from EP_cur, and $x_{cur}$ is a vector of unrealized new or retired capacity tracking linking variables from EP_cur.

inputs:

  • EP_cur - JuMP model from the current model stage $p$.
  • EP_next - JuMP model from the next model stage $p+1$.
  • var_name – Symbol representing the name of a JuMP variable array which contains total new or retired capacity tracking linking variables.
  • constr_name – Symbol representing the name of the array of linking JuMP constraints which contain total new or retired capacity tracking linking variables.

returns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.

source
GenX.initialize_cost_to_goMethod
initialize_cost_to_go(settings_d::Dict, EP::Model)

This function scales the model objective function so that costs are consistent with multi-stage modeling and introduces a cost-to-go function variable to the objective function.

The updated objective function $OBJ^{*}$ returned by this method takes the form:

\[\begin{aligned} OBJ^{*} = DF * OPEXMULT * OBJ + \alpha \end{aligned}\]

where $OBJ$ is the original objective function. $OBJ$ is scaled by two terms. The first is a discount factor (applied only in the non-myopic case), which discounts costs associated with the model stage $p$ to year-0 dollars:

\[\begin{aligned} DF = \frac{1}{(1+WACC)^{L*(p-1)}} \end{aligned}\]

where $WACC$ is the weighted average cost of capital, and $L$ is the length of each stage in years (both set in multi_stage_settings.yml)

The second term is a discounted sum of annual operational expenses incurred each year of a multi-year model stage:

\[\begin{aligned} & OPEXMULT = \sum^{L}_{l=1}\frac{1}{(1+WACC)^{l-1}} -\end{aligned}\]

Note that although the objective function contains investment costs, which occur only once and thus do not need to be scaled by OPEXMULT, these costs are multiplied by a factor of $\frac{1}{WACC}$ before being added to the objective function in investment_discharge_multi_stage(), investment_charge_multi_stage(), investment_energy_multi_stage(), and transmission_multi_stage(). Thus, this step scales these costs back to their correct value.

The cost-to-go function $\alpha$ represents an approximation of future costs given the investment and retirement decisions in the current stage. It is constructed through the addition of cuts to the cost-to-go function $\alpha$ during the backwards pass.

inputs:

  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • EP – JuMP model.

returns: JuMP model with updated objective function.

source
GenX.run_ddpMethod
run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)

This function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.

inputs:

  • models_d – Dictionary which contains a JuMP model for each model period.
  • setup - Dictionary object containing GenX settings and key parameters.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.

returns:

  • models_d – Dictionary which contains a JuMP model for each model stage, modified by this method.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.
source
GenX.write_multi_stage_outputsMethod
write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)

This function calls various methods which write multi-stage modeling outputs as .csv files.

inputs:

  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.
source
+\end{aligned}\]

Note that although the objective function contains investment costs, which occur only once and thus do not need to be scaled by OPEXMULT, these costs are multiplied by a factor of $\frac{1}{WACC}$ before being added to the objective function in investment_discharge_multi_stage(), investment_charge_multi_stage(), investment_energy_multi_stage(), and transmission_multi_stage(). Thus, this step scales these costs back to their correct value.

The cost-to-go function $\alpha$ represents an approximation of future costs given the investment and retirement decisions in the current stage. It is constructed through the addition of cuts to the cost-to-go function $\alpha$ during the backwards pass.

inputs:

  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • EP – JuMP model.

returns: JuMP model with updated objective function.

source
GenX.run_ddpMethod
run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)

This function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.

inputs:

  • models_d – Dictionary which contains a JuMP model for each model period.
  • setup - Dictionary object containing GenX settings and key parameters.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.

returns:

  • models_d – Dictionary which contains a JuMP model for each model stage, modified by this method.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.
source
GenX.write_multi_stage_outputsMethod
write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)

This function calls various methods which write multi-stage modeling outputs as .csv files.

inputs:

  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.
source
diff --git a/previews/PR655/Model_Reference/Multi_Stage/endogenous_retirement/index.html b/previews/PR655/Model_Reference/Multi_Stage/endogenous_retirement/index.html index 35d3176b63..005eeea77d 100644 --- a/previews/PR655/Model_Reference/Multi_Stage/endogenous_retirement/index.html +++ b/previews/PR655/Model_Reference/Multi_Stage/endogenous_retirement/index.html @@ -3,4 +3,4 @@ & RETCAP_{y,p} \geq \sum^p_{t=1} MINRET_{y,t} + \sum^r_{t=1}CAP_{y,t} - \sum^p_{t=1}RETCAP_{y,p} \end{aligned}\]

where $r \in \{1, ..., (p-1)\}$ is defined as the last stage such that if we built $y$ at the end of stage $r$, it would reach its end of life before the end of stage $p$. In other words, it is the largest index $r \in \{1, ..., (p-1)\}$ such that:

\[\begin{aligned} \sum^p_{t=r+1}StageLength_{t} \leq LifeTime_{y} -\end{aligned}\]

source
GenX.get_retirement_stageMethod
get_retirement_stage(cur_stage::Int, stage_len::Int, lifetime::Int, stage_lens::Array{Int, 1})

This function determines the model stage before which all newly built capacity must be retired. Used to enforce endogenous lifetime retirements in multi-stage modeling.

inputs:

  • cur_stage – An Int representing the current model stage $p$.
  • lifetime – An Int representing the lifetime of a particular resource.
  • stage_lens – An Int array representing the length $L$ of each model stage.

returns: An Int representing the model stage in before which the resource must retire due to endogenous lifetime retirements.

source
+\end{aligned}\]

source
GenX.get_retirement_stageMethod
get_retirement_stage(cur_stage::Int, stage_len::Int, lifetime::Int, stage_lens::Array{Int, 1})

This function determines the model stage before which all newly built capacity must be retired. Used to enforce endogenous lifetime retirements in multi-stage modeling.

inputs:

  • cur_stage – An Int representing the current model stage $p$.
  • lifetime – An Int representing the lifetime of a particular resource.
  • stage_lens – An Int array representing the length $L$ of each model stage.

returns: An Int representing the model stage in before which the resource must retire due to endogenous lifetime retirements.

source
diff --git a/previews/PR655/Model_Reference/Multi_Stage/multi_stage_overview/index.html b/previews/PR655/Model_Reference/Multi_Stage/multi_stage_overview/index.html index 2ea72df978..30face6a9e 100644 --- a/previews/PR655/Model_Reference/Multi_Stage/multi_stage_overview/index.html +++ b/previews/PR655/Model_Reference/Multi_Stage/multi_stage_overview/index.html @@ -1,2 +1,2 @@ -Multi-Stage Modeling Introduction · GenX

Multi-stage investment planning

Added in 0.3

GenX can be used to study the long-term evolution of the power system across multiple investment stages, in the following two ways:

  • The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here. This algorithm splits up a multi-stage investment planning problem into multiple, single-period sub-problems. Each period is solved iteratively as a separate linear program sub-problem (“forward pass”), and information from future periods is shared with past periods (“backwards pass”) so that investment decisions made in subsequent iterations reflect the contributions of present-day investments to future costs. The decomposition algorithm adapts previous nested Benders methods by handling integer and continuous state variables, although at the expense of losing its finite convergence property due to potential duality gap.
  • The user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as "myopic" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.

More information on this feature can be found in the section Multi-stage setup.

+Multi-Stage Modeling Introduction · GenX

Multi-stage investment planning

Added in 0.3

GenX can be used to study the long-term evolution of the power system across multiple investment stages, in the following two ways:

  • The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here. This algorithm splits up a multi-stage investment planning problem into multiple, single-period sub-problems. Each period is solved iteratively as a separate linear program sub-problem (“forward pass”), and information from future periods is shared with past periods (“backwards pass”) so that investment decisions made in subsequent iterations reflect the contributions of present-day investments to future costs. The decomposition algorithm adapts previous nested Benders methods by handling integer and continuous state variables, although at the expense of losing its finite convergence property due to potential duality gap.
  • The user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as "myopic" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.

More information on this feature can be found in the section Multi-stage setup.

diff --git a/previews/PR655/Model_Reference/Resources/curtailable_variable_renewable/index.html b/previews/PR655/Model_Reference/Resources/curtailable_variable_renewable/index.html index 90256b8ee3..5139bb6a60 100644 --- a/previews/PR655/Model_Reference/Resources/curtailable_variable_renewable/index.html +++ b/previews/PR655/Model_Reference/Resources/curtailable_variable_renewable/index.html @@ -1,7 +1,7 @@ Curtailable Variable Renewable · GenX

Curtailable Variable Renewables

GenX.curtailable_variable_renewable!Method
curtailable_variable_renewable!(EP::Model, inputs::Dict, setup::Dict)

This function defines the constraints for operation of variable renewable energy (VRE) resources whose output can be curtailed ($y \in \mathcal{VRE}$), such as utility-scale solar PV or wind power resources or run-of-river hydro resources that can spill water. The operational constraints for VRE resources are a function of each technology's time-dependent hourly capacity factor (or availability factor, $\rho^{max}_{y,z,t}$), in per unit terms, and the total available capacity ($\Delta^{total}_{y,z}$).

Power output in each time step For each VRE technology type $y$ and model zone $z$, the model allows for incorporating multiple bins with different parameters for resource quality ($\rho^{max}_{y,z,t}$), maximum availability ($\overline{\Omega_{y,z}}$) and investment cost ($\Pi^{INVEST}_{y,z}$, for example, due to interconnection cost differences). We define variables related to installed capacity ($\Delta_{y,z}$) and retired capacity ($\Delta_{y,z}$) for all resource bins for a particular VRE resource type $y$ and zone $z$ ($\overline{\mathcal{VRE}}^{y,z}$). However, the variable corresponding to power output in each timestep is only defined for the first bin. Parameter $VREIndex_{y,z}$, is used to keep track of the first bin, where $VREIndex_{y,z}=1$ for the first bin and $VREIndex_{y,z}=0$ for the remaining bins. This approach allows for modeling many different bins per VRE technology type and zone while significantly reducing the number of operational variable (related to power output for each time step from each bin) added to the model with every additional bin. Thus, the maximum power output for each VRE resource type in each zone is given by the following equation:

\[\begin{aligned} \Theta_{y,z,t} \leq \sum_{(x,z)\in \overline{\mathcal{VRE}}^{x,z}}{\rho^{max}_{x,z,t} \times \Delta^{total}_{x,z}} \hspace{2 cm} \forall y,z \in \{(y,z)|VREIndex_{y,z}=1, z \in \mathcal{Z}\},t \in \mathcal{T} -\end{aligned}\]

The above constraint is defined as an inequality instead of an equality to allow for VRE power output to be curtailed if desired. This adds the possibility of introducing VRE curtailment as an extra degree of freedom to guarantee that generation exactly meets demand in each time step. Note that if OperationalReserves=1 indicating that frequency regulation and operating reserves are modeled, then this function calls curtailable_variable_renewable_operational_reserves!(), which replaces the above constraints with a formulation inclusive of reserve provision.

source
GenX.curtailable_variable_renewable_operational_reserves!Method
curtailable_variable_renewable_operational_reserves!(EP::Model, inputs::Dict)

When modeling operating reserves, this function is called by curtailable_variable_renewable(), which modifies the constraint for maximum power output in each time step from VRE resources to account for procuring some of the available capacity for frequency regulation ($f_{y,z,t}$) and upward operating (spinning) reserves ($r_{y,z,t}$).

\[\begin{aligned} +\end{aligned}\]

The above constraint is defined as an inequality instead of an equality to allow for VRE power output to be curtailed if desired. This adds the possibility of introducing VRE curtailment as an extra degree of freedom to guarantee that generation exactly meets demand in each time step. Note that if OperationalReserves=1 indicating that frequency regulation and operating reserves are modeled, then this function calls curtailable_variable_renewable_operational_reserves!(), which replaces the above constraints with a formulation inclusive of reserve provision.

source
GenX.curtailable_variable_renewable_operational_reserves!Method
curtailable_variable_renewable_operational_reserves!(EP::Model, inputs::Dict)

When modeling operating reserves, this function is called by curtailable_variable_renewable(), which modifies the constraint for maximum power output in each time step from VRE resources to account for procuring some of the available capacity for frequency regulation ($f_{y,z,t}$) and upward operating (spinning) reserves ($r_{y,z,t}$).

\[\begin{aligned} \Theta_{y,z,t} + f_{y,z,t} + r_{y,z,t} \leq \sum_{(x,z)\in \overline{\mathcal{VRE}}^{x,z}}{\rho^{max}_{x,z,t}\times \Delta^{total}_{x,z}} \hspace{0.1 cm} \forall y,z \in \{(y,z)|VREIndex_{y,z}=1, z \in \mathcal{Z}\},t \in \mathcal{T} \end{aligned}\]

The amount of downward frequency regulation reserves also cannot exceed the current power output.

\[\begin{aligned} f_{y,z,t} \leq \Theta_{y,z,t} @@ -9,4 +9,4 @@ \end{aligned}\]

The amount of frequency regulation and operating reserves procured in each time step is bounded by the user-specified fraction ($\upsilon^{reg}_{y,z}$,$\upsilon^{rsv}_{y,z}$) of available capacity in each period for each reserve type, reflecting the maximum ramp rate for the VRE resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.

\[\begin{aligned} r_{y,z,t} \leq \upsilon^{rsv}_{y,z} \sum_{(x,z)\in \overline{\mathcal{VRE}}^{x,z}}{\rho^{max}_{x,z,t}\times \Delta^{total}_{x,z}} \hspace{1 cm} \forall y,z \in \{(y,z)|VREIndex_{y,z}=1, z \in \mathcal{Z}\},t \in \mathcal{T} \\ f_{y,z,t} \leq \upsilon^{reg}_{y,z} \sum_{(x,z)\in \overline{\mathcal{VRE}}^{x,z}}{\rho^{max}_{x,z,t}\times \Delta^{total}_{x,z}} \hspace{1 cm} \forall y,z \in \{(y,z)|VREIndex_{y,z}=1, z \in \mathcal{Z}\},t \in \mathcal{T} -\end{aligned}\]

source
+\end{aligned}\]

source diff --git a/previews/PR655/Model_Reference/Resources/electrolyzers/index.html b/previews/PR655/Model_Reference/Resources/electrolyzers/index.html index bf7d0fb921..953a0c9315 100644 --- a/previews/PR655/Model_Reference/Resources/electrolyzers/index.html +++ b/previews/PR655/Model_Reference/Resources/electrolyzers/index.html @@ -15,4 +15,4 @@ \end{aligned}\]

where $\eta^{electrolyzer}_y$ is the efficiency of the electrolyzer $y$ in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced and $\mathcal{Min kt}_y$ is the minimum annual quantity of hydrogen that must be produced by electrolyzer $y$ in kilotonnes. (See constraint 5 in the code)

Hourly clean supply matching constraint

This optional constraint (enabled by setting HydrogenHourlyMatching==1 in genx_settings.yml) requires generation from qualified resources ($y \in \mathcal{Qualified}$, indicated by Qualified_Hydrogen_Supply==1 in the resource .csv files) from within the same zone $z$ as the electrolyzers are located to be >= hourly consumption from electrolyzers in the zone (and any charging by qualified storage within the zone used to help increase electrolyzer utilization):

\[\begin{aligned} \sum_{y \in \{z \cap \mathcal{Qualified}\}} \Theta_{y,t} \geq \sum_{y \in \{z \cap \mathcal{EL}\}} \Pi_{y,t} + \sum_{y \in \{z \cap \mathcal{Qualified} \cap \mathcal{STOR}\}} \Pi_{y,t} \hspace{1cm} \forall z \in \mathcal{Z}, \forall t \in \mathcal{T}, -\end{aligned}\]

(See constraint 6 in the code)

This constraint permits modeling of the 'three pillars' requirements for clean hydrogen supply of (1) new clean supply (if only new clean resources are designated as eligible), (2) that is deliverable to the electrolyzer (assuming co-location within the same modeled zone = deliverability), and (3) produced within the same hour as the electrolyzer consumes power (otherwise known as 'additionality/new supply', 'deliverability', and 'temporal matching requirements') See Ricks, Xu & Jenkins (2023), ''Minimizing emissions from grid-based hydrogen production in the United States'' Environ. Res. Lett. 18 014025 doi:10.1088/1748-9326/acacb5 for more.

source +\end{aligned}\]

(See constraint 6 in the code)

This constraint permits modeling of the 'three pillars' requirements for clean hydrogen supply of (1) new clean supply (if only new clean resources are designated as eligible), (2) that is deliverable to the electrolyzer (assuming co-location within the same modeled zone = deliverability), and (3) produced within the same hour as the electrolyzer consumes power (otherwise known as 'additionality/new supply', 'deliverability', and 'temporal matching requirements') See Ricks, Xu & Jenkins (2023), ''Minimizing emissions from grid-based hydrogen production in the United States'' Environ. Res. Lett. 18 014025 doi:10.1088/1748-9326/acacb5 for more.

source diff --git a/previews/PR655/Model_Reference/Resources/flexible_demand/index.html b/previews/PR655/Model_Reference/Resources/flexible_demand/index.html index 165731600f..78deebfee8 100644 --- a/previews/PR655/Model_Reference/Resources/flexible_demand/index.html +++ b/previews/PR655/Model_Reference/Resources/flexible_demand/index.html @@ -10,4 +10,4 @@ \end{aligned}\]

A similar constraints maximum time steps of demand advancement. This is done by enforcing the sum of demand deferred ($\Pi_{y,t}$) in the following $\tau^{advance}_{y}$ time steps (e.g., t + 1 to t + $\tau^{advance}_{y}$) to be greater than or equal to the total level of energy deferred during time $t$ (-$\Gamma_{y,t}$). The negative sign is included to account for the established sign convention that treat demand deferred in advance of the actual demand is defined to be negative.

\[\begin{aligned} \sum_{e=t+1}^{t+\tau^{advance}_{y,z}}{\Pi_{y,z,e}} \geq -\Gamma_{y,z,t} \hspace{4 cm} \forall y \in \mathcal{DF}, z \in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

If $t$ is first time step of the year (or the first time step of the representative period), then the above two constraints are implemented to look back over the last n time steps, starting with the last time step of the year (or the last time step of the representative period). This time-wrapping implementation is similar to the time-wrapping implementations used for defining the storage balance constraints for hydropower reservoir resources and energy storage resources.

source +\end{aligned}\]

If $t$ is first time step of the year (or the first time step of the representative period), then the above two constraints are implemented to look back over the last n time steps, starting with the last time step of the year (or the last time step of the representative period). This time-wrapping implementation is similar to the time-wrapping implementations used for defining the storage balance constraints for hydropower reservoir resources and energy storage resources.

source diff --git a/previews/PR655/Model_Reference/Resources/hydro_inter_period_linkage/index.html b/previews/PR655/Model_Reference/Resources/hydro_inter_period_linkage/index.html index 34c518e7ba..21a9ec7bdf 100644 --- a/previews/PR655/Model_Reference/Resources/hydro_inter_period_linkage/index.html +++ b/previews/PR655/Model_Reference/Resources/hydro_inter_period_linkage/index.html @@ -14,4 +14,4 @@ \end{aligned}\]

Finally, the next constraint enforces that the initial storage level for each input period $n$ must be less than the installed energy capacity limit. This constraint ensures that installed energy storage capacity is consistent with the state of charge during both the operational time periods $t$ during each sample period $m$ as well as at the start of each chronologically ordered input period $n$ in the full annual time series.

\[\begin{aligned} Q_{o,z,n} \leq \Delta^{total, energy}_{o,z} \quad \forall n \in \mathcal{N}, o \in \mathcal{O}^{LDES} -\end{aligned}\]

source +\end{aligned}\]

source diff --git a/previews/PR655/Model_Reference/Resources/hydro_res/index.html b/previews/PR655/Model_Reference/Resources/hydro_res/index.html index 8a750b347c..684c2c2b72 100644 --- a/previews/PR655/Model_Reference/Resources/hydro_res/index.html +++ b/previews/PR655/Model_Reference/Resources/hydro_res/index.html @@ -20,7 +20,7 @@ \end{aligned}\]

Reservoir energy capacity constraint In case the reservoir capacity is known ($y \in W^{cap}$), then an additional constraint enforces the total stored energy in each time step to be less than or equal to the available reservoir capacity. Here, the reservoir capacity is defined multiplying the parameter, $\mu^{stor}_{y,z}$ with the available power capacity.

\[\begin{aligned} \Gamma_{y,z, t} \leq \mu^{stor}_{y,z}\times \Delta^{total}_{y,z} \hspace{4 cm} \forall y \in \mathcal{W}^{cap}, z \in \mathcal{Z}, t\in \mathcal{T} -\end{aligned}\]

source
GenX.hydro_res_operational_reserves!Method
hydro_res_operational_reserves!(EP::Model, inputs::Dict)

This module defines the modified constraints and additional constraints needed when modeling operating reserves

Modifications when operating reserves are modeled When modeling operating reserves, the constraints regarding maximum power flow limits are modified to account for procuring some of the available capacity for frequency regulation ($f_{y,z,t}$) and "updward" operating (or spinning) reserves ($r_{y,z,t}$).

\[\begin{aligned} +\end{aligned}\]

source
GenX.hydro_res_operational_reserves!Method
hydro_res_operational_reserves!(EP::Model, inputs::Dict)

This module defines the modified constraints and additional constraints needed when modeling operating reserves

Modifications when operating reserves are modeled When modeling operating reserves, the constraints regarding maximum power flow limits are modified to account for procuring some of the available capacity for frequency regulation ($f_{y,z,t}$) and "updward" operating (or spinning) reserves ($r_{y,z,t}$).

\[\begin{aligned} \Theta_{y,z,t} + f_{y,z,t} +r_{y,z,t} \leq \times \Delta^{total}_{y,z} \hspace{4 cm} \forall y \in \mathcal{W}, z \in \mathcal{Z}, t\in \mathcal{T} \end{aligned}\]

The amount of downward frequency regulation reserves cannot exceed the current power output.

\[\begin{aligned} @@ -31,4 +31,4 @@ \hspace{4 cm} \forall y \in \mathcal{W}, z \in \mathcal{Z}, t \in \mathcal{T} \\ r_{y,z, t} \leq \upsilon^{rsv}_{y,z}\times \Delta^{total}_{y,z} \hspace{4 cm} \forall y \in \mathcal{W}, z \in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

source
+\end{aligned}\]

source diff --git a/previews/PR655/Model_Reference/Resources/investment_charge/index.html b/previews/PR655/Model_Reference/Resources/investment_charge/index.html index e340d2fce2..c3b1e1ca2c 100644 --- a/previews/PR655/Model_Reference/Resources/investment_charge/index.html +++ b/previews/PR655/Model_Reference/Resources/investment_charge/index.html @@ -13,4 +13,4 @@ & \sum_{y \in \mathcal{O}^{asym} } \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST,charge}_{y,z} \times \Omega^{charge}_{y,z}) + (\pi^{FOM,charge}_{y,z} \times \Delta^{total,charge}_{y,z})\right) -\end{aligned}\]

source +\end{aligned}\]

source diff --git a/previews/PR655/Model_Reference/Resources/investment_energy/index.html b/previews/PR655/Model_Reference/Resources/investment_energy/index.html index cb7a182679..5ea5132c17 100644 --- a/previews/PR655/Model_Reference/Resources/investment_energy/index.html +++ b/previews/PR655/Model_Reference/Resources/investment_energy/index.html @@ -13,4 +13,4 @@ & \sum_{y \in \mathcal{O} } \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST,energy}_{y,z} \times \Omega^{energy}_{y,z}) + (\pi^{FOM,energy}_{y,z} \times \Delta^{total,energy}_{y,z})\right) -\end{aligned}\]

source +\end{aligned}\]

source diff --git a/previews/PR655/Model_Reference/Resources/long_duration_storage/index.html b/previews/PR655/Model_Reference/Resources/long_duration_storage/index.html index be9888b545..34a4759d31 100644 --- a/previews/PR655/Model_Reference/Resources/long_duration_storage/index.html +++ b/previews/PR655/Model_Reference/Resources/long_duration_storage/index.html @@ -14,4 +14,4 @@ \end{aligned}\]

If the capacity reserve margin constraint is enabled, a similar set of constraints is used to track the evolution of the energy held in reserve across representative periods. The main linking constraint is as follows:

\[\begin{aligned} & \Gamma^{CRM}_{o,z,(m-1)\times \tau^{period}+1 } =\left(1-\eta_{o,z}^{loss}\right)\times \left(\Gamma^{CRM}_{o,z,m\times \tau^{period}} -\Delta Q_{o,z,m}\right) + \\ & \frac{1}{\eta_{o,z}^{discharge}}\Theta^{CRM}_{o,z,(m-1)\times \tau^{period}+1} - \eta_{o,z}^{charge}\Pi^{CRM}_{o,z,(m-1)\times \tau^{period}+1} \quad \forall o \in \mathcal{O}^{LDES}, z \in \mathcal{Z}, m \in \mathcal{M} -\end{aligned}\]

All other constraints are identical to those used to track the actual state of charge, except with the new variables $Q^{CRM}_{o,z,n}$ and $\Delta Q^{CRM}_{o,z,n}$ used in place of $Q_{o,z,n}$ and $\Delta Q_{o,z,n}$, respectively.

source +\end{aligned}\]

All other constraints are identical to those used to track the actual state of charge, except with the new variables $Q^{CRM}_{o,z,n}$ and $\Delta Q^{CRM}_{o,z,n}$ used in place of $Q_{o,z,n}$ and $\Delta Q_{o,z,n}$, respectively.

source diff --git a/previews/PR655/Model_Reference/Resources/maintenance/index.html b/previews/PR655/Model_Reference/Resources/maintenance/index.html index a9d9ad9929..8e79e4a862 100644 --- a/previews/PR655/Model_Reference/Resources/maintenance/index.html +++ b/previews/PR655/Model_Reference/Resources/maintenance/index.html @@ -31,36 +31,36 @@ commitment for operational variables. Creates maintenance-tracking variables and adds their Symbols to two Sets in `inputs`. -Adds constraints which act on the vCOMMIT-like variable.source
GenX.resources_with_maintenanceFunction
resources_with_maintenance(df::DataFrame)::Vector{Int}
+Adds constraints which act on the vCOMMIT-like variable.
source
GenX.resources_with_maintenanceFunction
resources_with_maintenance(df::DataFrame)::Vector{Int}
 
 Get a vector of the R_ID's of all resources listed in a dataframe
 that have maintenance requirements. If there are none, return an empty vector.
 
 This method takes a specific dataframe because compound resources may have their
-data in multiple dataframes.
source
GenX.maintenance_down_nameFunction
maintenance_down_name(resource_component::AbstractString)::String
+data in multiple dataframes.
source
GenX.maintenance_down_nameFunction
maintenance_down_name(resource_component::AbstractString)::String
 
 JuMP variable name to control whether a resource-component is down for maintenance.
-Here resource-component could be a whole resource or a component (for complex resources).
source
GenX.maintenance_shut_nameFunction
maintenance_shut_name(resource_component::AbstractString)::String
+Here resource-component could be a whole resource or a component (for complex resources).
source
GenX.maintenance_shut_nameFunction
maintenance_shut_name(resource_component::AbstractString)::String
 
 JuMP variable name to control when a resource-components begins maintenance.
-Here resource-component could be a whole resource or a component (for complex resources).
source
GenX.controlling_maintenance_start_hoursFunction
controlling_maintenance_start_hours(p::Int, t::Int, maintenance_duration::Int, maintenance_begin_hours::UnitRange{Int64})
+Here resource-component could be a whole resource or a component (for complex resources).
source
GenX.controlling_maintenance_start_hoursFunction
controlling_maintenance_start_hours(p::Int, t::Int, maintenance_duration::Int, maintenance_begin_hours::UnitRange{Int64})
 
 p: hours_per_subperiod
 t: the current hour
 maintenance_duration: length of a maintenance period
-maintenance_begin_hours: collection of hours in which maintenance is allowed to start
source
GenX.ensure_maintenance_variable_records!Function
ensure_maintenance_variable_records!(dict::Dict)
+maintenance_begin_hours: collection of hours in which maintenance is allowed to start
source
GenX.ensure_maintenance_variable_records!Function
ensure_maintenance_variable_records!(dict::Dict)
 
 dict: a dictionary of model data
 
 This should be called by each method that adds maintenance formulations,
-to ensure that certain entries in the model data dict exist.
source
GenX.has_maintenanceFunction
has_maintenance(dict::Dict)
+to ensure that certain entries in the model data dict exist.
source
GenX.has_maintenanceFunction
has_maintenance(dict::Dict)
 
 dict: a dictionary of model data
 
 Checks whether the dictionary contains listings of maintenance-related variable names.
-This is true only after `maintenance_formulation!` has been called.
source
GenX.maintenance_down_variablesFunction
maintenance_down_variables(dict::Dict)
+This is true only after `maintenance_formulation!` has been called.
source
GenX.maintenance_down_variablesFunction
maintenance_down_variables(dict::Dict)
 
 dict: a dictionary of model data
 
 get listings of maintenance-related variable names.
-This is available only after `maintenance_formulation!` has been called.
source
+This is available only after `maintenance_formulation!` has been called.source diff --git a/previews/PR655/Model_Reference/Resources/must_run/index.html b/previews/PR655/Model_Reference/Resources/must_run/index.html index 95e7e6f542..c1d074e235 100644 --- a/previews/PR655/Model_Reference/Resources/must_run/index.html +++ b/previews/PR655/Model_Reference/Resources/must_run/index.html @@ -2,4 +2,4 @@ Must Run · GenX

Must Run

GenX.must_run!Method
must_run!(EP::Model, inputs::Dict, setup::Dict)

This function defines the constraints for operation of `must-run' or non-dispatchable resources, such as rooftop solar systems that do not receive dispatch signals, run-of-river hydroelectric facilities without the ability to spill water, or cogeneration systems that must produce a fixed quantity of heat in each time step. This resource type can also be used to model baseloaded or self-committed thermal generators that do not respond to economic dispatch.

For must-run resources ($y\in \mathcal{MR}$) output in each time period $t$ must exactly equal the available capacity factor times the installed capacity, not allowing for curtailment. These resources are also not eligible for contributing to frequency regulation or operating reserve requirements.

\[\begin{aligned} \Theta_{y,z,t} = \rho^{max}_{y,z,t}\times \Delta^{total}_{y,z} \hspace{4 cm} \forall y \in \mathcal{MR}, z \in \mathcal{Z},t \in \mathcal{T} -\end{aligned}\]

source
+\end{aligned}\]

source diff --git a/previews/PR655/Model_Reference/Resources/resource/index.html b/previews/PR655/Model_Reference/Resources/resource/index.html index 1e34b5f6e3..f63829d98d 100644 --- a/previews/PR655/Model_Reference/Resources/resource/index.html +++ b/previews/PR655/Model_Reference/Resources/resource/index.html @@ -1,39 +1,39 @@ -Resource types · GenX

Resource types and function interfaces

GenX.resource_typesConstant
resource_types

Name of the type of resources available in the model.

Possible values:

  • :Thermal
  • :Vre
  • :Hydro
  • :Storage
  • :MustRun
  • :FlexDemand
  • :VreStorage
  • :Electrolyzer
source
Base.findallMethod
findall(f::Function, rs::Vector{<:AbstractResource})

Find all resources in the vector rs that satisfy the condition given by the function f. Return the resource id instead of the vector index.

Arguments

  • f::Function: The condition function.
  • rs::Vector{<:AbstractResource}: The vector of resources.

Returns

  • Vector: The vector of resource ids.

Examples

julia> findall(r -> max_cap_mwh(r) != 0, gen.Storage)
+Resource types · GenX

Resource types and function interfaces

GenX.resource_typesConstant
resource_types

Name of the type of resources available in the model.

Possible values:

  • :Thermal
  • :Vre
  • :Hydro
  • :Storage
  • :MustRun
  • :FlexDemand
  • :VreStorage
  • :Electrolyzer
source
Base.findallMethod
findall(f::Function, rs::Vector{<:AbstractResource})

Find all resources in the vector rs that satisfy the condition given by the function f. Return the resource id instead of the vector index.

Arguments

  • f::Function: The condition function.
  • rs::Vector{<:AbstractResource}: The vector of resources.

Returns

  • Vector: The vector of resource ids.

Examples

julia> findall(r -> max_cap_mwh(r) != 0, gen.Storage)
 3-element Vector{Int64}:
  48
  49
- 50
source
Base.getMethod
Base.get(r::AbstractResource, sym::Symbol, default)

Retrieves the value of a specific attribute from an AbstractResource object. If the attribute exists, its value is returned; otherwise, the default value is returned.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.
  • default: The default value to return if the attribute does not exist.

Returns:

  • The value of the attribute if it exists in the parent object, default otherwise.
source
Base.getpropertyMethod
Base.getproperty(r::AbstractResource, sym::Symbol)

Allows to access the attributes of an AbstractResource object using dot syntax. It checks if the attribute exists in the object and returns its value, otherwise it throws an ErrorException indicating that the attribute does not exist.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.

Returns:

  • The value of the attribute if it exists in the parent object.

Throws:

  • ErrorException: If the attribute does not exist in the resource.
source
Base.getpropertyMethod
Base.getproperty(rs::Vector{<:AbstractResource}, sym::Symbol)

Allows to access attributes of a vector of AbstractResource objects using dot syntax. If the sym is an element of the resource_types constant, it returns all resources of that type. Otherwise, it returns the value of the attribute for each resource in the vector.

Arguments:

  • rs::Vector{<:AbstractResource}: The vector of AbstractResource objects.
  • sym::Symbol: The symbol representing the attribute name or a type from resource_types.

Returns:

  • If sym is an element of the resource_types constant, it returns a vector containing all resources of that type.
  • If sym is an attribute name, it returns a vector containing the value of the attribute for each resource.

Examples

julia> vre_gen = gen.Vre;  # gen vector of resources
+ 50
source
Base.getMethod
Base.get(r::AbstractResource, sym::Symbol, default)

Retrieves the value of a specific attribute from an AbstractResource object. If the attribute exists, its value is returned; otherwise, the default value is returned.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.
  • default: The default value to return if the attribute does not exist.

Returns:

  • The value of the attribute if it exists in the parent object, default otherwise.
source
Base.getpropertyMethod
Base.getproperty(r::AbstractResource, sym::Symbol)

Allows to access the attributes of an AbstractResource object using dot syntax. It checks if the attribute exists in the object and returns its value, otherwise it throws an ErrorException indicating that the attribute does not exist.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.

Returns:

  • The value of the attribute if it exists in the parent object.

Throws:

  • ErrorException: If the attribute does not exist in the resource.
source
Base.getpropertyMethod
Base.getproperty(rs::Vector{<:AbstractResource}, sym::Symbol)

Allows to access attributes of a vector of AbstractResource objects using dot syntax. If the sym is an element of the resource_types constant, it returns all resources of that type. Otherwise, it returns the value of the attribute for each resource in the vector.

Arguments:

  • rs::Vector{<:AbstractResource}: The vector of AbstractResource objects.
  • sym::Symbol: The symbol representing the attribute name or a type from resource_types.

Returns:

  • If sym is an element of the resource_types constant, it returns a vector containing all resources of that type.
  • If sym is an attribute name, it returns a vector containing the value of the attribute for each resource.

Examples

julia> vre_gen = gen.Vre;  # gen vector of resources
 julia> typeof(vre_gen)
 Vector{Vre} (alias for Array{Vre, 1})
-julia> vre_gen.zone
source
Base.haskeyMethod
haskey(r::AbstractResource, sym::Symbol)

Check if an AbstractResource object has a specific attribute. It returns a boolean value indicating whether the attribute exists in the parent object.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.

Returns:

  • true if the attribute exists in the parent object, false otherwise.
source
Base.pairsMethod
pairs(r::AbstractResource)

Return an iterator of key-value pairs with the attributes of a given resource.

Arguments

  • r::AbstractResource: The resource.

Returns

  • Pairs: An iterator of key-value pairs over the attributes.
source
Base.setindex!Method
Base.setindex!(rs::Vector{<:AbstractResource}, value::Vector, sym::Symbol)

Define dot syntax for setting the attributes specified by sym to the corresponding values in value for a vector of resources.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • value::Vector: The vector of values to set for the attribute.
  • sym::Symbol: The symbol representing the attribute to set.

Returns

  • rs::Vector{<:AbstractResource}: The updated vector of resources.
source
Base.setproperty!Method
setproperty!(r::AbstractResource, sym::Symbol, value)

Allows to set the attribute sym of an AbstractResource object using dot syntax.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.
  • value: The value to set for the attribute.
source
Base.setproperty!Method
Base.setproperty!(rs::Vector{<:AbstractResource}, sym::Symbol, value::Vector)

Set the attributes specified by sym to the corresponding values in value for a vector of resources.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • sym::Symbol: The symbol representing the attribute to set.
  • value::Vector: The vector of values to set for the attribute.

Returns

  • rs::Vector{<:AbstractResource}: The updated vector of resources.
source
Base.showMethod
show(io::IO, r::AbstractResource)

Print the attributes of the given resource.

Arguments

  • io::IO: The IO stream to print to.
  • r::AbstractResource: The resource.
source
GenX.attributesMethod
attributes(r::AbstractResource)

Returns a tuple of the attribute names of the given resource.

Arguments

  • r::AbstractResource: The resource.

Returns

  • Tuple: A tuple with symbols representing the attribute names.
source
GenX.electrolyzerMethod
electrolyzer(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all electrolyzer resources in the vector rs.

source
GenX.flex_demandMethod
flex_demand(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all flexible demand resources in the vector rs.

source
GenX.has_all_options_contributingMethod
has_all_options_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource

Check if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res contribute to min retirement.

Arguments

  • retrofit_res::AbstractResource: The retrofit resource.
  • rs::Vector{T}: The vector of resources.

Returns

  • Bool: True if all retrofit options contribute to min retirement, otherwise false.
source
GenX.has_all_options_not_contributingMethod
has_all_options_not_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource

Check if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res do not contribute to min retirement.

Arguments

  • retrofit_res::AbstractResource: The retrofit resource.
  • rs::Vector{T}: The vector of resources.

Returns

  • Bool: True if all retrofit options do not contribute to min retirement, otherwise false.
source
GenX.hydroMethod
hydro(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all hydro resources in the vector rs.

source
GenX.ids_withMethod
ids_with(rs::Vector{T}, f::Function, default=default_zero) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by f is not equal to default.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The getter of the attribute.
  • default: The default value of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with attribute not equal to default.

Examples

julia> ids_with(gen.Thermal, existing_cap_mw)
+julia> vre_gen.zone
source
Base.haskeyMethod
haskey(r::AbstractResource, sym::Symbol)

Check if an AbstractResource object has a specific attribute. It returns a boolean value indicating whether the attribute exists in the parent object.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.

Returns:

  • true if the attribute exists in the parent object, false otherwise.
source
Base.pairsMethod
pairs(r::AbstractResource)

Return an iterator of key-value pairs with the attributes of a given resource.

Arguments

  • r::AbstractResource: The resource.

Returns

  • Pairs: An iterator of key-value pairs over the attributes.
source
Base.setindex!Method
Base.setindex!(rs::Vector{<:AbstractResource}, value::Vector, sym::Symbol)

Define dot syntax for setting the attributes specified by sym to the corresponding values in value for a vector of resources.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • value::Vector: The vector of values to set for the attribute.
  • sym::Symbol: The symbol representing the attribute to set.

Returns

  • rs::Vector{<:AbstractResource}: The updated vector of resources.
source
Base.setproperty!Method
setproperty!(r::AbstractResource, sym::Symbol, value)

Allows to set the attribute sym of an AbstractResource object using dot syntax.

Arguments:

  • r::AbstractResource: The resource object.
  • sym::Symbol: The symbol representing the attribute name.
  • value: The value to set for the attribute.
source
Base.setproperty!Method
Base.setproperty!(rs::Vector{<:AbstractResource}, sym::Symbol, value::Vector)

Set the attributes specified by sym to the corresponding values in value for a vector of resources.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • sym::Symbol: The symbol representing the attribute to set.
  • value::Vector: The vector of values to set for the attribute.

Returns

  • rs::Vector{<:AbstractResource}: The updated vector of resources.
source
Base.showMethod
show(io::IO, r::AbstractResource)

Print the attributes of the given resource.

Arguments

  • io::IO: The IO stream to print to.
  • r::AbstractResource: The resource.
source
GenX.attributesMethod
attributes(r::AbstractResource)

Returns a tuple of the attribute names of the given resource.

Arguments

  • r::AbstractResource: The resource.

Returns

  • Tuple: A tuple with symbols representing the attribute names.
source
GenX.electrolyzerMethod
electrolyzer(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all electrolyzer resources in the vector rs.

source
GenX.flex_demandMethod
flex_demand(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all flexible demand resources in the vector rs.

source
GenX.has_all_options_contributingMethod
has_all_options_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource

Check if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res contribute to min retirement.

Arguments

  • retrofit_res::AbstractResource: The retrofit resource.
  • rs::Vector{T}: The vector of resources.

Returns

  • Bool: True if all retrofit options contribute to min retirement, otherwise false.
source
GenX.has_all_options_not_contributingMethod
has_all_options_not_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource

Check if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res do not contribute to min retirement.

Arguments

  • retrofit_res::AbstractResource: The retrofit resource.
  • rs::Vector{T}: The vector of resources.

Returns

  • Bool: True if all retrofit options do not contribute to min retirement, otherwise false.
source
GenX.hydroMethod
hydro(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all hydro resources in the vector rs.

source
GenX.ids_withMethod
ids_with(rs::Vector{T}, f::Function, default=default_zero) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by f is not equal to default.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The getter of the attribute.
  • default: The default value of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with attribute not equal to default.

Examples

julia> ids_with(gen.Thermal, existing_cap_mw)
 4-element Vector{Int64}:
  21
  22
  23
  24
 julia> existing_cap_mw(gen[21])
-7.0773
source
GenX.ids_withMethod
ids_with(rs::Vector{T}, name::Symbol, default=default_zero) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by name is not equal to the default value of the attribute.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the attribute.
  • default: The default value of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with attribute not equal to default.

Examples

julia> ids_with(gen.Thermal, :existing_cap_mw)
+7.0773
source
GenX.ids_withMethod
ids_with(rs::Vector{T}, name::Symbol, default=default_zero) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by name is not equal to the default value of the attribute.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the attribute.
  • default: The default value of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with attribute not equal to default.

Examples

julia> ids_with(gen.Thermal, :existing_cap_mw)
 4-element Vector{Int64}:
  21
  22
  23
  24
 julia> existing_cap_mw(gen[21])
-7.0773
source
GenX.ids_with_all_options_contributingMethod
ids_with_all_options_contributing(rs::Vector{T}) where T <: AbstractResource

Find the resource ids of the retrofit units in the vector rs where all retrofit options contribute to min retirement.

Arguments

  • rs::Vector{T}: The vector of resources.

Returns

  • Vector{Int64}: The vector of resource ids.
source
GenX.ids_with_all_options_not_contributingMethod
ids_with_all_options_not_contributing(rs::Vector{T}) where T <: AbstractResource

Find the resource ids of the retrofit units in the vector rs where all retrofit options do not contribute to min retirement.

Arguments

  • rs::Vector{T}: The vector of resources.

Returns

  • Vector{Int64}: The vector of resource ids.
source
GenX.ids_with_nonnegMethod
ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by f is non-negative.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The getter of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with non-negative attribute.

Examples

julia> ids_with_nonneg(gen, max_cap_mw)
source
GenX.ids_with_nonnegMethod
ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by name is non-negative.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with non-negative attribute.

Examples

julia> ids_with_nonneg(gen, max_cap_mw)
source
GenX.ids_with_policyMethod
ids_with_policy(rs::Vector{T}, f::Function; tag::Int64) where T <: AbstractResource

Function for finding resources in a vector rs where the policy specified by f with tag equal to tag is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The policy getter function.
  • tag::Int64: The tag of the policy.

Returns

  • ids (Vector{Int64}): The vector of resource ids with a positive value for policy f and tag tag.
source
GenX.ids_with_policyMethod

idswithpolicy(rs::Vector{T}, name::Symbol; tag::Int64) where T <: AbstractResource

Function for finding resources in a vector rs where the policy specified by name with tag equal to tag is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the policy.
  • tag::Int64: The tag of the policy.

Returns

  • ids (Vector{Int64}): The vector of resource ids with a positive value for policy name and tag tag.
source
GenX.ids_with_positiveMethod
ids_with_positive(rs::Vector{T}, f::Function) where T <: AbstractResource

Function for finding indices of resources in a vector rs where the attribute specified by f is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The getter of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with positive attribute.

Examples

julia> ids_with_positive(gen, max_cap_mw)
+7.0773
source
GenX.ids_with_all_options_contributingMethod
ids_with_all_options_contributing(rs::Vector{T}) where T <: AbstractResource

Find the resource ids of the retrofit units in the vector rs where all retrofit options contribute to min retirement.

Arguments

  • rs::Vector{T}: The vector of resources.

Returns

  • Vector{Int64}: The vector of resource ids.
source
GenX.ids_with_all_options_not_contributingMethod
ids_with_all_options_not_contributing(rs::Vector{T}) where T <: AbstractResource

Find the resource ids of the retrofit units in the vector rs where all retrofit options do not contribute to min retirement.

Arguments

  • rs::Vector{T}: The vector of resources.

Returns

  • Vector{Int64}: The vector of resource ids.
source
GenX.ids_with_nonnegMethod
ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by f is non-negative.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The getter of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with non-negative attribute.

Examples

julia> ids_with_nonneg(gen, max_cap_mw)
source
GenX.ids_with_nonnegMethod
ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource

Function for finding resources in a vector rs where the attribute specified by name is non-negative.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with non-negative attribute.

Examples

julia> ids_with_nonneg(gen, max_cap_mw)
source
GenX.ids_with_policyMethod
ids_with_policy(rs::Vector{T}, f::Function; tag::Int64) where T <: AbstractResource

Function for finding resources in a vector rs where the policy specified by f with tag equal to tag is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The policy getter function.
  • tag::Int64: The tag of the policy.

Returns

  • ids (Vector{Int64}): The vector of resource ids with a positive value for policy f and tag tag.
source
GenX.ids_with_policyMethod

idswithpolicy(rs::Vector{T}, name::Symbol; tag::Int64) where T <: AbstractResource

Function for finding resources in a vector rs where the policy specified by name with tag equal to tag is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the policy.
  • tag::Int64: The tag of the policy.

Returns

  • ids (Vector{Int64}): The vector of resource ids with a positive value for policy name and tag tag.
source
GenX.ids_with_positiveMethod
ids_with_positive(rs::Vector{T}, f::Function) where T <: AbstractResource

Function for finding indices of resources in a vector rs where the attribute specified by f is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • f::Function: The getter of the attribute.

Returns

  • ids (Vector{Int64}): The vector of resource ids with positive attribute.

Examples

julia> ids_with_positive(gen, max_cap_mw)
 3-element Vector{Int64}:
  3 
  4
  5
 julia> max_cap_mw(gen[3])
-4.888236
source
GenX.ids_with_positiveMethod
ids_with_positive(rs::Vector{T}, name::Symbol) where T <: AbstractResource

Function for finding indices of resources in a vector rs where the attribute specified by name is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the attribute.

Returns

  • Vector{Int64}: The vector of resource ids with positive attribute.

Examples

julia> ids_with_positive(gen, :max_cap_mw)
+4.888236
source
GenX.ids_with_positiveMethod
ids_with_positive(rs::Vector{T}, name::Symbol) where T <: AbstractResource

Function for finding indices of resources in a vector rs where the attribute specified by name is positive.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • name::Symbol: The name of the attribute.

Returns

  • Vector{Int64}: The vector of resource ids with positive attribute.

Examples

julia> ids_with_positive(gen, :max_cap_mw)
 3-element Vector{Int64}:
  3 
  4
  5
 julia> max_cap_mw(gen[3])
-4.888236
source
GenX.must_runMethod
must_run(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all must-run resources in the vector rs.

source
GenX.resource_by_nameMethod
resource_by_name(rs::Vector{<:AbstractResource}, name::AbstractString)

Find the resource with name in the vector rs.

Arguments

  • rs: A vector of resources.
  • name: The name of the resource.

Returns

  • AbstractResource: The resource with the name name.
source
GenX.resources_in_retrofit_cluster_by_ridMethod
resources_in_retrofit_cluster_by_rid(rs::Vector{<:AbstractResource}, cluster_id::String)

Find RID's of resources with retrofit cluster id `clusterid`.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • cluster_id::String: The retrofit cluster id.

Returns

  • Vector{Int64}: The vector of resource ids in the retrofit cluster.
source
GenX.solarMethod
solar(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located solar resources in the vector rs.

source
GenX.storageMethod
storage(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all storage resources in the vector rs.

source
GenX.storage_ac_chargeMethod
storage_ac_charge(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located storage resources in the vector rs that charge AC.

source
GenX.storage_ac_dischargeMethod
storage_ac_discharge(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located storage resources in the vector rs that discharge AC.

source
GenX.storage_dc_chargeMethod
storage_dc_charge(rs::Vector{T}) where T <: AbstractResource
-Returns the indices of all co-located storage resources in the vector `rs` that charge DC.
source
GenX.storage_dc_dischargeMethod
storage_dc_discharge(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located storage resources in the vector rs that discharge DC.

source
GenX.thermalMethod
thermal(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all thermal resources in the vector rs.

source
GenX.validate_boolean_attributeMethod
validate_boolean_attribute(r::AbstractResource, attr::Symbol)

Validate that the attribute attr in the resource r is boolean {0, 1}.

Arguments

  • r::AbstractResource: The resource.
  • attr::Symbol: The name of the attribute.
source
GenX.vreMethod
vre(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all Vre resources in the vector rs.

source
GenX.vre_storMethod
vre_stor(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all VRE_STOR resources in the vector rs.

source
GenX.windMethod
wind(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located wind resources in the vector rs.

source
GenX.@interfaceMacro
interface(name, default=default_zero, type=AbstractResource)

Define a function interface for accessing the attribute specified by name in a resource of type type.

Arguments

  • name: The name of the attribute.
  • default: The default value to return if the attribute is not found.
  • type: The type of the resource.

Returns

  • Function: The generated function.

Examples

julia> @interface max_cap_mw 0 Vre
+4.888236
source
GenX.must_runMethod
must_run(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all must-run resources in the vector rs.

source
GenX.resource_by_nameMethod
resource_by_name(rs::Vector{<:AbstractResource}, name::AbstractString)

Find the resource with name in the vector rs.

Arguments

  • rs: A vector of resources.
  • name: The name of the resource.

Returns

  • AbstractResource: The resource with the name name.
source
GenX.resources_in_retrofit_cluster_by_ridMethod
resources_in_retrofit_cluster_by_rid(rs::Vector{<:AbstractResource}, cluster_id::String)

Find RID's of resources with retrofit cluster id `clusterid`.

Arguments

  • rs::Vector{<:AbstractResource}: The vector of resources.
  • cluster_id::String: The retrofit cluster id.

Returns

  • Vector{Int64}: The vector of resource ids in the retrofit cluster.
source
GenX.solarMethod
solar(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located solar resources in the vector rs.

source
GenX.storageMethod
storage(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all storage resources in the vector rs.

source
GenX.storage_ac_chargeMethod
storage_ac_charge(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located storage resources in the vector rs that charge AC.

source
GenX.storage_ac_dischargeMethod
storage_ac_discharge(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located storage resources in the vector rs that discharge AC.

source
GenX.storage_dc_chargeMethod
storage_dc_charge(rs::Vector{T}) where T <: AbstractResource
+Returns the indices of all co-located storage resources in the vector `rs` that charge DC.
source
GenX.storage_dc_dischargeMethod
storage_dc_discharge(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located storage resources in the vector rs that discharge DC.

source
GenX.thermalMethod
thermal(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all thermal resources in the vector rs.

source
GenX.validate_boolean_attributeMethod
validate_boolean_attribute(r::AbstractResource, attr::Symbol)

Validate that the attribute attr in the resource r is boolean {0, 1}.

Arguments

  • r::AbstractResource: The resource.
  • attr::Symbol: The name of the attribute.
source
GenX.vreMethod
vre(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all Vre resources in the vector rs.

source
GenX.vre_storMethod
vre_stor(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all VRE_STOR resources in the vector rs.

source
GenX.windMethod
wind(rs::Vector{T}) where T <: AbstractResource

Returns the indices of all co-located wind resources in the vector rs.

source
GenX.@interfaceMacro
interface(name, default=default_zero, type=AbstractResource)

Define a function interface for accessing the attribute specified by name in a resource of type type.

Arguments

  • name: The name of the attribute.
  • default: The default value to return if the attribute is not found.
  • type: The type of the resource.

Returns

  • Function: The generated function.

Examples

julia> @interface max_cap_mw 0 Vre
 julia> max_cap_mw(gen.Vre[3])
 4.888236
 julia> max_cap_mw.(gen.Vre) # vectorized
@@ -42,4 +42,4 @@
   0.0
   4.888236
  20.835569
-  9.848441999999999
source
+ 9.848441999999999
source
diff --git a/previews/PR655/Model_Reference/Resources/retrofit/index.html b/previews/PR655/Model_Reference/Resources/retrofit/index.html index af8d4948a1..67b3053270 100644 --- a/previews/PR655/Model_Reference/Resources/retrofit/index.html +++ b/previews/PR655/Model_Reference/Resources/retrofit/index.html @@ -1,4 +1,4 @@ Retrofit · GenX

Retrofit

GenX.retrofitMethod
retrofit(EP::Model, inputs::Dict)

This function defines the constraints for operation of retrofit technologies, including but not limited to carbon capture and thermal energy storage.

For retrofittable source technologies $y$ and retrofit technologies $r$ in the same region $z$ and retrofit cluster $id$, (i.e. $y \in RS(id)$ and $r \in RO(id)$), the total retrofit capacity $\Omega_{r}$ that may be installed is constrained by the available retrofittable capacity $P_{y}$ as well as the efficiency ${ef}_{r}$ of the retrofit technology.

\[\begin{aligned} \sum_{y \in RS(id)}P_{y} = \sum_{r \in RO(id)}\frac{\Omega_{r}}{{ef}_{r}} \quad \quad \quad \quad \forall id \in {RETROFIT}, -\end{aligned}\]

where ${RETROFIT}$ represents the set of all retrofit IDs (clusters) in the model.

source
+\end{aligned}\]

where ${RETROFIT}$ represents the set of all retrofit IDs (clusters) in the model.

source diff --git a/previews/PR655/Model_Reference/Resources/storage/index.html b/previews/PR655/Model_Reference/Resources/storage/index.html index 8379007438..4f0b6d4d65 100644 --- a/previews/PR655/Model_Reference/Resources/storage/index.html +++ b/previews/PR655/Model_Reference/Resources/storage/index.html @@ -40,4 +40,4 @@ \end{aligned}\]

Finally, the constraints on maximum discharge rate are replaced by the following, to account for capacity contributed to regulation and reserves:

\[\begin{aligned} & \Theta_{o,z,t} + \Theta^{CRM}_{o,z,t} + f^{discharge}_{o,z,t} + r^{discharge}_{o,z,t} \leq \Delta^{total}_{o,z} & \quad \forall o \in \mathcal{O}, z \in \mathcal{Z}, t \in \mathcal{T}\\ & \Theta_{o,z,t} + \Theta^{CRM}_{o,z,t} + f^{discharge}_{o,z,t} + r^{discharge}_{o,z,t} \leq \Gamma_{o,z,t-1} & \quad \forall o \in \mathcal{O}, z \in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

The above reserve related constraints are established by storage_all_operational_reserves!() in storage_all.jl

source +\end{aligned}\]

The above reserve related constraints are established by storage_all_operational_reserves!() in storage_all.jl

source diff --git a/previews/PR655/Model_Reference/Resources/storage_all/index.html b/previews/PR655/Model_Reference/Resources/storage_all/index.html index 7e5435aecc..ce8aebeefb 100644 --- a/previews/PR655/Model_Reference/Resources/storage_all/index.html +++ b/previews/PR655/Model_Reference/Resources/storage_all/index.html @@ -1,2 +1,2 @@ -Storage All · GenX

Storage All

GenX.storage_all!Method
storage_all!(EP::Model, inputs::Dict, setup::Dict)

Sets up variables and constraints common to all storage resources. See storage() in storage.jl for description of constraints.

source
+Storage All · GenX

Storage All

GenX.storage_all!Method
storage_all!(EP::Model, inputs::Dict, setup::Dict)

Sets up variables and constraints common to all storage resources. See storage() in storage.jl for description of constraints.

source
diff --git a/previews/PR655/Model_Reference/Resources/storage_asymmetric/index.html b/previews/PR655/Model_Reference/Resources/storage_asymmetric/index.html index d6eb70e216..21b903fca4 100644 --- a/previews/PR655/Model_Reference/Resources/storage_asymmetric/index.html +++ b/previews/PR655/Model_Reference/Resources/storage_asymmetric/index.html @@ -1,2 +1,2 @@ -Storage Asymmetric · GenX

Storage Asymmetric

GenX.storage_asymmetric!Method
storage_asymmetric!(EP::Model, inputs::Dict, setup::Dict)

Sets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.

source
GenX.storage_asymmetric_operational_reserves!Method
storage_asymmetric_operational_reserves!(EP::Model, inputs::Dict)

Sets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.

source
+Storage Asymmetric · GenX

Storage Asymmetric

GenX.storage_asymmetric!Method
storage_asymmetric!(EP::Model, inputs::Dict, setup::Dict)

Sets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.

source
GenX.storage_asymmetric_operational_reserves!Method
storage_asymmetric_operational_reserves!(EP::Model, inputs::Dict)

Sets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.

source
diff --git a/previews/PR655/Model_Reference/Resources/storage_symmetric/index.html b/previews/PR655/Model_Reference/Resources/storage_symmetric/index.html index 1c2024e61a..1761861183 100644 --- a/previews/PR655/Model_Reference/Resources/storage_symmetric/index.html +++ b/previews/PR655/Model_Reference/Resources/storage_symmetric/index.html @@ -1,2 +1,2 @@ -Storage Symmetric · GenX

Storage Symmetric

GenX.storage_symmetric!Method
storage_symmetric!(EP::Model, inputs::Dict, setup::Dict)

Sets up variables and constraints specific to storage resources with symmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.

source
GenX.storage_symmetric_operational_reserves!Method
storage_symmetric_operational_reserves!(EP::Model, inputs::Dict)

Sets up variables and constraints specific to storage resources with symmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.

source
+Storage Symmetric · GenX

Storage Symmetric

GenX.storage_symmetric!Method
storage_symmetric!(EP::Model, inputs::Dict, setup::Dict)

Sets up variables and constraints specific to storage resources with symmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.

source
GenX.storage_symmetric_operational_reserves!Method
storage_symmetric_operational_reserves!(EP::Model, inputs::Dict)

Sets up variables and constraints specific to storage resources with symmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.

source
diff --git a/previews/PR655/Model_Reference/Resources/thermal/index.html b/previews/PR655/Model_Reference/Resources/thermal/index.html index f22ff3aeda..25c16b7aca 100644 --- a/previews/PR655/Model_Reference/Resources/thermal/index.html +++ b/previews/PR655/Model_Reference/Resources/thermal/index.html @@ -1,6 +1,6 @@ -Thermal · GenX

Thermal

GenX.thermal!Method
thermal!(EP::Model, inputs::Dict, setup::Dict)

The thermal module creates decision variables, expressions, and constraints related to thermal power plants e.g. coal, oil or natural gas steam plants, natural gas combined cycle and combustion turbine plants, nuclear, hydrogen combustion etc. This module uses the following 'helper' functions in separate files: thermal_commit() for thermal resources subject to unit commitment decisions and constraints (if any) and thermal_no_commit() for thermal resources not subject to unit commitment (if any).

source
GenX.thermal_plant_effective_capacityMethod
thermal_plant_effective_capacity(EP::Model,
+Thermal · GenX

Thermal

GenX.thermal!Method
thermal!(EP::Model, inputs::Dict, setup::Dict)

The thermal module creates decision variables, expressions, and constraints related to thermal power plants e.g. coal, oil or natural gas steam plants, natural gas combined cycle and combustion turbine plants, nuclear, hydrogen combustion etc. This module uses the following 'helper' functions in separate files: thermal_commit() for thermal resources subject to unit commitment decisions and constraints (if any) and thermal_no_commit() for thermal resources not subject to unit commitment (if any).

source
GenX.thermal_plant_effective_capacityMethod
thermal_plant_effective_capacity(EP::Model,
                                  inputs::Dict,
                                  resources::Vector{Int},
                                  capres_zone::Int,
-                                 timesteps::Vector{Int})::Matrix{Float64}

Effective capacity in a capacity reserve margin zone for certain resources in the given timesteps.

source
+ timesteps::Vector{Int})::Matrix{Float64}

Effective capacity in a capacity reserve margin zone for certain resources in the given timesteps.

source
diff --git a/previews/PR655/Model_Reference/Resources/thermal_commit/index.html b/previews/PR655/Model_Reference/Resources/thermal_commit/index.html index 42994cc28f..5af9ee173f 100644 --- a/previews/PR655/Model_Reference/Resources/thermal_commit/index.html +++ b/previews/PR655/Model_Reference/Resources/thermal_commit/index.html @@ -1,5 +1,5 @@ -Thermal Commit · GenX

Thermal Commit

GenX.thermal_commit!Method
thermal_commit!(EP::Model, inputs::Dict, setup::Dict)

This function defines the operating constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decision ($y \in UC$).

We model capacity investment decisions and commitment and cycling (start-up, shut-down) of thermal generators using the integer clustering technique developed in Palmintier, 2011, Palmintier, 2013, and Palmintier, 2014. In a typical binary unit commitment formulation, each unit is either on or off. With the clustered unit commitment formulation, one or more cluster(s) of similar generators are clustered by type and zone (typically using heat rate and fixed O\&M cost to create clusters), and the integer commitment state variable for each cluster varies from zero to the number of units in the cluster, $\frac{\Delta^{total}_{y,z}}{\Omega^{size}_{y,z}}$. As discussed in \cite{Palmintier2014}, this approach replaces the large set of binary commitment decisions and associated constraints, which scale directly with the number of individual units, with a smaller set of integer commitment states and constraints, one for each cluster $y$. The dimensionality of the problem thus scales with the number of units of a given type in each zone, rather than by the number of discrete units, significantly improving computational efficiency. However, this method entails the simplifying assumption that all clustered units have identical parameters (e.g., capacity size, ramp rates, heat rate) and that all committed units in a given time step $t$ are operating at the same power output per unit.

Power balance expression

This function adds the sum of power generation from thermal units subject to unit commitment ($\Theta_{y \in UC,t \in T,z \in Z}$) to the power balance expression.

Startup and shutdown events (thermal plant cycling)

Capacitated limits on unit commitment decision variables

Thermal resources subject to unit commitment ($y \in \mathcal{UC}$) adhere to the following constraints on commitment states, startup events, and shutdown events, which limit each decision to be no greater than the maximum number of discrete units installed (as per the following three constraints):

\[\begin{aligned} +Thermal Commit · GenX

Thermal Commit

GenX.thermal_commit!Method
thermal_commit!(EP::Model, inputs::Dict, setup::Dict)

This function defines the operating constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decision ($y \in UC$).

We model capacity investment decisions and commitment and cycling (start-up, shut-down) of thermal generators using the integer clustering technique developed in Palmintier, 2011, Palmintier, 2013, and Palmintier, 2014. In a typical binary unit commitment formulation, each unit is either on or off. With the clustered unit commitment formulation, one or more cluster(s) of similar generators are clustered by type and zone (typically using heat rate and fixed O\&M cost to create clusters), and the integer commitment state variable for each cluster varies from zero to the number of units in the cluster, $\frac{\Delta^{total}_{y,z}}{\Omega^{size}_{y,z}}$. As discussed in \cite{Palmintier2014}, this approach replaces the large set of binary commitment decisions and associated constraints, which scale directly with the number of individual units, with a smaller set of integer commitment states and constraints, one for each cluster $y$. The dimensionality of the problem thus scales with the number of units of a given type in each zone, rather than by the number of discrete units, significantly improving computational efficiency. However, this method entails the simplifying assumption that all clustered units have identical parameters (e.g., capacity size, ramp rates, heat rate) and that all committed units in a given time step $t$ are operating at the same power output per unit.

Power balance expression

This function adds the sum of power generation from thermal units subject to unit commitment ($\Theta_{y \in UC,t \in T,z \in Z}$) to the power balance expression.

Startup and shutdown events (thermal plant cycling)

Capacitated limits on unit commitment decision variables

Thermal resources subject to unit commitment ($y \in \mathcal{UC}$) adhere to the following constraints on commitment states, startup events, and shutdown events, which limit each decision to be no greater than the maximum number of discrete units installed (as per the following three constraints):

\[\begin{aligned} \nu_{y,z,t} \leq \frac{\Delta^{\text{total}}_{y,z}}{\Omega^{size}_{y,z}} \hspace{1.5cm} \forall y \in \mathcal{UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} \end{aligned}\]

\[\begin{aligned} @@ -33,7 +33,7 @@ \end{aligned}\]

\[\begin{aligned} \frac{\overline{\Delta_{y,z}} + \Omega_{y,z} - \Delta_{y,z}}{\Omega^{size}_{y,z}} - \nu_{y,z,t} \geq \displaystyle \sum_{\hat{t} = t-(\tau^{down}_{y,z}-1)}^t \zeta_{y,z,\hat{t}} \hspace{1.5cm} \forall y \in \mathcal{UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} -\end{aligned}\]

(See Constraints 9-10 in the code)

where $\tau_{y,z}^{up|down}$ is the minimum up or down time for units in generating cluster $y$ in zone $z$.

Like with the ramping constraints, the minimum up and down constraint time also wrap around from the start of each time period to the end of each period. It is recommended that users of GenX must use longer subperiods than the longest min up/down time if modeling UC. Otherwise, the model will report error.

source
GenX.thermal_commit_operational_reserves!Method
thermal_commit_operational_reserves!(EP::Model, inputs::Dict)

This function is called by the thermal_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decisions.

Maximum contributions to frequency regulation and reserves

When modeling frequency regulation and reserves contributions, thermal units subject to unit commitment adhere to the following constraints which limit the maximum contribution to regulation and reserves in each time step to a specified maximum fraction ($,\upsilon^{rsv}_{y,z}$) of the commitment capacity in that time step ($(\Omega^{size}_{y,z} \cdot \nu_{y,z,t})$):

\[\begin{aligned} +\end{aligned}\]

(See Constraints 9-10 in the code)

where $\tau_{y,z}^{up|down}$ is the minimum up or down time for units in generating cluster $y$ in zone $z$.

Like with the ramping constraints, the minimum up and down constraint time also wrap around from the start of each time period to the end of each period. It is recommended that users of GenX must use longer subperiods than the longest min up/down time if modeling UC. Otherwise, the model will report error.

source
GenX.thermal_commit_operational_reserves!Method
thermal_commit_operational_reserves!(EP::Model, inputs::Dict)

This function is called by the thermal_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decisions.

Maximum contributions to frequency regulation and reserves

When modeling frequency regulation and reserves contributions, thermal units subject to unit commitment adhere to the following constraints which limit the maximum contribution to regulation and reserves in each time step to a specified maximum fraction ($,\upsilon^{rsv}_{y,z}$) of the commitment capacity in that time step ($(\Omega^{size}_{y,z} \cdot \nu_{y,z,t})$):

\[\begin{aligned} f_{y,z,t} \leq \upsilon^{reg}_{y,z} \times \rho^{max}_{y,z,t} (\Omega^{size}_{y,z} \times \nu_{y,z,t}) \hspace{1.5cm} \forall y \in \mathcal{UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} \end{aligned}\]

\[\begin{aligned} r_{y,z,t} \leq \upsilon^{rsv}_{y,z} \times \rho^{max}_{y,z,t} (\Omega^{size}_{y,z} \times \nu_{y,z,t}) \hspace{1.5cm} \forall y \in \mathcal{UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} @@ -43,4 +43,4 @@ \end{aligned}\]

\[\begin{aligned} \Theta_{y,z,t} + f_{y,z,t} + r_{y,z,t} \leq \rho^{max}_{y,z,t} \times \Omega^{size}_{y,z} \times \nu_{y,z,t} \hspace{1.5cm} \forall y \in \mathcal{UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} -\end{aligned}\]

source
+\end{aligned}\]

source
diff --git a/previews/PR655/Model_Reference/Resources/thermal_no_commit/index.html b/previews/PR655/Model_Reference/Resources/thermal_no_commit/index.html index 4bd578ae9c..606e40bff0 100644 --- a/previews/PR655/Model_Reference/Resources/thermal_no_commit/index.html +++ b/previews/PR655/Model_Reference/Resources/thermal_no_commit/index.html @@ -9,7 +9,7 @@ \end{aligned}\]

\[\begin{aligned} \Theta_{y,z,t} \leq \rho^{max}_{y,z,t} \times \Delta^{total}_{y,z} \hspace{1cm} \forall y \in \mathcal{H \setminus UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} -\end{aligned}\]

(See Constraints 3-4 in the code)

source
GenX.thermal_no_commit_operational_reserves!Method
thermal_no_commit_operational_reserves!(EP::Model, inputs::Dict)

This function is called by the thermal_no_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants not subject to unit commitment constraints on power plant start-ups and shut-down decisions.

Maximum contributions to frequency regulation and reserves

Thermal units not subject to unit commitment adhere instead to the following constraints on maximum reserve and regulation contributions:

\[\begin{aligned} +\end{aligned}\]

(See Constraints 3-4 in the code)

source
GenX.thermal_no_commit_operational_reserves!Method
thermal_no_commit_operational_reserves!(EP::Model, inputs::Dict)

This function is called by the thermal_no_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants not subject to unit commitment constraints on power plant start-ups and shut-down decisions.

Maximum contributions to frequency regulation and reserves

Thermal units not subject to unit commitment adhere instead to the following constraints on maximum reserve and regulation contributions:

\[\begin{aligned} f_{y,z,t} \leq \upsilon^{reg}_{y,z} \times \rho^{max}_{y,z,t} \Delta^{\text{total}}_{y,z} \hspace{1cm} \forall y \in \mathcal{H \setminus UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} \end{aligned}\]

\[\begin{aligned} r_{y,z,t} \leq \upsilon^{rsv}_{y,z} \times \rho^{max}_{y,z,t} \Delta^{\text{total}}_{y,z} \hspace{1cm} \forall y \in \mathcal{H \setminus UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} @@ -19,4 +19,4 @@ \end{aligned}\]

\[\begin{aligned} \Theta_{y,z,t} + f_{y,z,t} + r_{y,z,t} \leq \rho^{max}_{y,z,t} \times \Delta^{\text{total}}_{y,z} \hspace{1cm} \forall y \in \mathcal{H \setminus UC}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} -\end{aligned}\]

Note there are multiple versions of these constraints in the code in order to avoid creation of unecessary constraints and decision variables for thermal units unable to provide regulation and/or reserves contributions due to input parameters (e.g. Reg_Max=0 and/or RSV_Max=0).

source
+\end{aligned}\]

Note there are multiple versions of these constraints in the code in order to avoid creation of unecessary constraints and decision variables for thermal units unable to provide regulation and/or reserves contributions due to input parameters (e.g. Reg_Max=0 and/or RSV_Max=0).

source diff --git a/previews/PR655/Model_Reference/Resources/vre_stor/index.html b/previews/PR655/Model_Reference/Resources/vre_stor/index.html index f8c5763a28..40e3bf8e61 100644 --- a/previews/PR655/Model_Reference/Resources/vre_stor/index.html +++ b/previews/PR655/Model_Reference/Resources/vre_stor/index.html @@ -24,7 +24,7 @@ & \sum_{y \in \mathcal{VS}^{inv}} \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST, inv}_{y,z} \times \Omega^{inv}_{y,z}) + (\pi^{FOM, inv}_{y,z} \times \Delta^{total,inv}_{y,z})\right) -\end{aligned}\]

source
GenX.investment_charge_vre_stor!Method
investment_charge_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function activates the decision variables and constraints for asymmetric storage resources (independent charge and discharge power capacities (any STOR flag = 2)). For asymmetric storage resources, the function is enabled so charging and discharging can occur either through DC or AC capabilities. For example, a storage resource can be asymmetrically charged and discharged via DC capabilities or a storage resource could be charged via AC capabilities and discharged through DC capabilities. This module is configured such that both AC and DC charging (or discharging) cannot simultaneously occur.

The total charge/discharge DC and AC capacities of each resource are defined as the sum of the existing charge/discharge DC and AC capacities plus the newly invested charge/discharge DC and AC capacities minus any retired charge/discharge DC and AC capacities:

\[\begin{aligned} +\end{aligned}\]

source
GenX.investment_charge_vre_stor!Method
investment_charge_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function activates the decision variables and constraints for asymmetric storage resources (independent charge and discharge power capacities (any STOR flag = 2)). For asymmetric storage resources, the function is enabled so charging and discharging can occur either through DC or AC capabilities. For example, a storage resource can be asymmetrically charged and discharged via DC capabilities or a storage resource could be charged via AC capabilities and discharged through DC capabilities. This module is configured such that both AC and DC charging (or discharging) cannot simultaneously occur.

The total charge/discharge DC and AC capacities of each resource are defined as the sum of the existing charge/discharge DC and AC capacities plus the newly invested charge/discharge DC and AC capacities minus any retired charge/discharge DC and AC capacities:

\[\begin{aligned} & \Delta^{total,dc,dis}_{y,z} =(\overline{\Delta^{dc,dis}_{y,z}}+\Omega^{dc,dis}_{y,z}-\Delta^{dc,dis}_{y,z}) \quad \forall y \in \mathcal{VS}^{asym,dc,dis}, z \in \mathcal{Z} \\ & \Delta^{total,dc,cha}_{y,z} =(\overline{\Delta^{dc,cha}_{y,z}}+\Omega^{dc,cha}_{y,z}-\Delta^{dc,cha}_{y,z}) \quad \forall y \in \mathcal{VS}^{asym,dc,cha}, z \in \mathcal{Z} \\ & \Delta^{total,ac,dis}_{y,z} =(\overline{\Delta^{ac,dis}_{y,z}}+\Omega^{ac,dis}_{y,z}-\Delta^{ac,dis}_{y,z}) \quad \forall y \in \mathcal{VS}^{asym,ac,dis}, z \in \mathcal{Z} \\ @@ -88,11 +88,11 @@ & + \sum_{y \in \mathcal{VS}^{asym,ac,cha} } \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST,ac,cha}_{y,z} \times \Omega^{ac,cha}_{y,z}) + (\pi^{FOM,ac,cha}_{y,z} \times \Delta^{total,ac,cha}_{y,z})\right) -\end{aligned}\]

source
GenX.lds_vre_stor!Method
lds_vre_stor!(EP::Model, inputs::Dict)

This function defines the decision variables, expressions, and constraints for any long duration energy storage component of each co-located VRE and storage generator ( there is more than one representative period and LDS_VRE_STOR=1 in the Vre_and_stor_data.csv).

These constraints follow the same formulation that is outlined by the function long_duration_storage!() in the storage module. One constraint changes, which links the state of charge between the start of periods for long duration energy storage resources because there are options to charge and discharge these resources through AC and DC capabilities. The main linking constraint changes to:

\[\begin{aligned} +\end{aligned}\]

source
GenX.lds_vre_stor!Method
lds_vre_stor!(EP::Model, inputs::Dict)

This function defines the decision variables, expressions, and constraints for any long duration energy storage component of each co-located VRE and storage generator ( there is more than one representative period and LDS_VRE_STOR=1 in the Vre_and_stor_data.csv).

These constraints follow the same formulation that is outlined by the function long_duration_storage!() in the storage module. One constraint changes, which links the state of charge between the start of periods for long duration energy storage resources because there are options to charge and discharge these resources through AC and DC capabilities. The main linking constraint changes to:

\[\begin{aligned} & \Gamma_{y,z,(m-1)\times \tau^{period}+1 } =\left(1-\eta_{y,z}^{loss}\right) \times \left(\Gamma_{y,z,m\times \tau^{period}} -\Delta Q_{y,z,m}\right) \\ & - \frac{\Theta^{dc}_{y,z,(m-1) \times \tau^{period}+1}}{\eta_{y,z}^{discharge,dc}} - \frac{\Theta^{ac}_{y,z,(m-1)\times \tau^{period}+1}}{\eta_{y,z}^{discharge,ac}} \\ & + \eta_{y,z}^{charge,dc} \times \Pi^{dc}_{y,z,(m-1)\times \tau^{period}+1} + \eta_{y,z}^{charge,ac} \times \Pi^{ac}_{y,z,(m-1)\times \tau^{period}+1} \quad \forall y \in \mathcal{VS}^{LDES}, z \in \mathcal{Z}, m \in \mathcal{M} -\end{aligned}\]

The rest of the long duration energy storage constraints are copied and applied to the co-located VRE and storage module for any long duration energy storage resources $y \in \mathcal{VS}^{LDES}$ from the long-duration storage module. Capacity reserve margin constraints for long duration energy storage resources are further elaborated upon in vre_stor_capres!().

source
GenX.solar_vre_stor!Method
solar_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function defines the decision variables, expressions, and constraints for the solar PV component of each co-located VRE and storage generator.

The total solar PV capacity of each resource is defined as the sum of the existing solar PV capacity plus the newly invested solar PV capacity minus any retired solar PV capacity:

\[\begin{aligned} +\end{aligned}\]

The rest of the long duration energy storage constraints are copied and applied to the co-located VRE and storage module for any long duration energy storage resources $y \in \mathcal{VS}^{LDES}$ from the long-duration storage module. Capacity reserve margin constraints for long duration energy storage resources are further elaborated upon in vre_stor_capres!().

source
GenX.solar_vre_stor!Method
solar_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function defines the decision variables, expressions, and constraints for the solar PV component of each co-located VRE and storage generator.

The total solar PV capacity of each resource is defined as the sum of the existing solar PV capacity plus the newly invested solar PV capacity minus any retired solar PV capacity:

\[\begin{aligned} & \Delta^{total, pv}_{y,z} = (\overline{\Delta^{pv}_{y,z}} + \Omega^{pv}_{y,z} - \Delta^{pv}_{y,z}) \quad \forall y \in \mathcal{VS}^{pv}, z \in \mathcal{Z} \end{aligned}\]

One cannot retire more solar PV capacity than existing solar PV capacity:

\[\begin{aligned} & \Delta^{pv}_{y,z} \leq \overline{\Delta^{pv}_{y,z}} @@ -112,7 +112,7 @@ & \sum_{y \in \mathcal{VS}^{pv}} \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST, pv}_{y,z} \times \Omega^{pv}_{y,z}) + (\pi^{FOM, pv}_{y,z} \times \Delta^{total,pv}_{y,z}) \right) \\ & + \sum_{y \in \mathcal{VS}^{pv}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} (\pi^{VOM, pv}_{y,z} \times \eta^{inverter}_{y,z} \times \Theta^{pv}_{y,z,t}) -\end{aligned}\]

source
GenX.stor_vre_stor!Method
stor_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function defines the decision variables, expressions, and constraints for the storage component of each co-located VRE and storage generator. A wide range of energy storage devices (all $y \in \mathcal{VS}^{stor}$) can be modeled in GenX, using one of two generic storage formulations: (1) storage technologies with symmetric charge and discharge capacity (all $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{sym,ac}$), such as lithium-ion batteries and most other electrochemical storage devices that use the same components for both charge and discharge; and (2) storage technologies that employ distinct and potentially asymmetric charge and discharge capacities (all $y \in \mathcal{VS}^{asym,dc,dis} \cup y \in \mathcal{VS}^{asym,dc,cha} \cup y \in \mathcal{VS}^{asym,ac,dis} \cup y \in \mathcal{VS}^{asym,ac,cha}$), such as most thermal storage technologies or hydrogen electrolysis/storage/fuel cell or combustion turbine systems. The following constraints apply to all storage resources, $y \in \mathcal{VS}^{stor}$, regardless of whether or not the storage has symmetric or asymmetric charging/discharging capabilities or varying durations of discharge.

The total storage energy capacity of each resource is defined as the sum of the existing storage energy capacity plus the newly invested storage energy capacity minus any retired storage energy capacity:

\[\begin{aligned} +\end{aligned}\]

source
GenX.stor_vre_stor!Method
stor_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function defines the decision variables, expressions, and constraints for the storage component of each co-located VRE and storage generator. A wide range of energy storage devices (all $y \in \mathcal{VS}^{stor}$) can be modeled in GenX, using one of two generic storage formulations: (1) storage technologies with symmetric charge and discharge capacity (all $y \in \mathcal{VS}^{sym,dc} \cup y \in \mathcal{VS}^{sym,ac}$), such as lithium-ion batteries and most other electrochemical storage devices that use the same components for both charge and discharge; and (2) storage technologies that employ distinct and potentially asymmetric charge and discharge capacities (all $y \in \mathcal{VS}^{asym,dc,dis} \cup y \in \mathcal{VS}^{asym,dc,cha} \cup y \in \mathcal{VS}^{asym,ac,dis} \cup y \in \mathcal{VS}^{asym,ac,cha}$), such as most thermal storage technologies or hydrogen electrolysis/storage/fuel cell or combustion turbine systems. The following constraints apply to all storage resources, $y \in \mathcal{VS}^{stor}$, regardless of whether or not the storage has symmetric or asymmetric charging/discharging capabilities or varying durations of discharge.

The total storage energy capacity of each resource is defined as the sum of the existing storage energy capacity plus the newly invested storage energy capacity minus any retired storage energy capacity:

\[\begin{aligned} & \Delta^{total,energy}_{y,z} = (\overline{\Delta^{energy}_{y,z}}+\Omega^{energy}_{y,z}-\Delta^{energy}_{y,z}) \quad \forall y \in \mathcal{VS}^{stor}, z \in \mathcal{Z} \end{aligned}\]

One cannot retire more energy capacity than existing energy capacity:

\[\begin{aligned} &\Delta^{energy}_{y,z} \leq \overline{\Delta^{energy}_{y,z}} @@ -154,7 +154,7 @@ & + \sum_{y \in \mathcal{VS}^{sym,dc} \cup \mathcal{VS}^{asym,dc,cha}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} (\pi^{VOM,dc,cha}_{y,z} \times \frac{\Pi^{dc}_{y,z,t}}{\eta^{inverter}_{y,z}}) \\ & + \sum_{y \in \mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,dis}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} (\pi^{VOM,ac,dis}_{y,z} \times \Theta^{ac}_{y,z,t}) \\ & + \sum_{y \in \mathcal{VS}^{sym,ac} \cup \mathcal{VS}^{asym,ac,cha}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} (\pi^{VOM,ac,cha}_{y,z} \times \Pi^{ac}_{y,z,t}) -\end{aligned}\]

source
GenX.vre_stor!Method
vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This module enables the modeling of 1) co-located VRE and energy storage technologies, and 2) optimized interconnection sizing for VREs. Utility-scale solar PV and/or wind VRE technologies can be modeled at the same site with or without storage technologies. Storage resources can be charged/discharged behind the meter through the inverter (DC) and through AC charging/discharging capabilities. Each resource can be configured to have any combination of the following components: solar PV, wind, DC discharging/charging storage, and AC discharging/charging storage resources. For storage resources, both long duration energy storage and short-duration energy storage can be modeled, via asymmetric or symmetric charging and discharging options. Each resource connects to the grid via a grid connection component, which is the only required decision variable that each resource must have. If the configured resource has either solar PV and/or DC discharging/charging storage capabilities, an inverter decision variable is also created. The full module with the decision variables and interactions can be found below.

Configurable Co-located VRE and Storage Module Interactions and Decision Variables Figure. Configurable Co-located VRE and Storage Module Interactions and Decision Variables

This module is split such that functions are called for each configurable component of a co-located resource: inverter_vre_stor(), solar_vre_stor!(), wind_vre_stor!(), stor_vre_stor!(), lds_vre_stor!(), and investment_charge_vre_stor!(). The function vre_stor!() specifically ensures that all necessary functions are called to activate the appropriate constraints, creates constraints that apply to multiple components (i.e. inverter and grid connection balances and maximums), and activates all of the policies that have been created (minimum capacity requirements, maximum capacity requirements, capacity reserve margins, operating reserves, and energy share requirements can all be turned on for this module). Note that not all of these variables are indexed by each co-located VRE and storage resource (for example, some co-located resources may only have a solar PV component and battery technology or just a wind component). Thus, the function vre_stor!() ensures indexing issues do not arise across the various potential configurations of co-located VRE and storage module but showcases all constraints as if each decision variable (that may be only applicable to certain components) is indexed by each $y \in \mathcal{VS}$ for readability.

The first constraint is created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains and regardless of the policies invoked for the module. This constraint represents the energy balance, ensuring net DC power (discharge of battery, PV generation, and charge of battery) and net AC power (discharge of battery, wind generation, and charge of battery) are equal to the technology's total discharging to and charging from the grid:

\[\begin{aligned} +\end{aligned}\]

source
GenX.vre_stor!Method
vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This module enables the modeling of 1) co-located VRE and energy storage technologies, and 2) optimized interconnection sizing for VREs. Utility-scale solar PV and/or wind VRE technologies can be modeled at the same site with or without storage technologies. Storage resources can be charged/discharged behind the meter through the inverter (DC) and through AC charging/discharging capabilities. Each resource can be configured to have any combination of the following components: solar PV, wind, DC discharging/charging storage, and AC discharging/charging storage resources. For storage resources, both long duration energy storage and short-duration energy storage can be modeled, via asymmetric or symmetric charging and discharging options. Each resource connects to the grid via a grid connection component, which is the only required decision variable that each resource must have. If the configured resource has either solar PV and/or DC discharging/charging storage capabilities, an inverter decision variable is also created. The full module with the decision variables and interactions can be found below.

Configurable Co-located VRE and Storage Module Interactions and Decision Variables Figure. Configurable Co-located VRE and Storage Module Interactions and Decision Variables

This module is split such that functions are called for each configurable component of a co-located resource: inverter_vre_stor(), solar_vre_stor!(), wind_vre_stor!(), stor_vre_stor!(), lds_vre_stor!(), and investment_charge_vre_stor!(). The function vre_stor!() specifically ensures that all necessary functions are called to activate the appropriate constraints, creates constraints that apply to multiple components (i.e. inverter and grid connection balances and maximums), and activates all of the policies that have been created (minimum capacity requirements, maximum capacity requirements, capacity reserve margins, operating reserves, and energy share requirements can all be turned on for this module). Note that not all of these variables are indexed by each co-located VRE and storage resource (for example, some co-located resources may only have a solar PV component and battery technology or just a wind component). Thus, the function vre_stor!() ensures indexing issues do not arise across the various potential configurations of co-located VRE and storage module but showcases all constraints as if each decision variable (that may be only applicable to certain components) is indexed by each $y \in \mathcal{VS}$ for readability.

The first constraint is created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains and regardless of the policies invoked for the module. This constraint represents the energy balance, ensuring net DC power (discharge of battery, PV generation, and charge of battery) and net AC power (discharge of battery, wind generation, and charge of battery) are equal to the technology's total discharging to and charging from the grid:

\[\begin{aligned} & \Theta_{y,z,t} - \Pi_{y,z,t} = \Theta_{y,z,t}^{wind} + \Theta_{y,z,t}^{ac} - \Pi_{y,z,t}^{ac} + \eta^{inverter}_{y,z} \times (\Theta_{y,z,t}^{pv} + \Theta_{y,z,t}^{dc}) - \frac{\Pi^{dc}_{y,z,t}}{\eta^{inverter}_{y,z}} \\ & \forall y \in \mathcal{VS}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} \end{aligned}\]

The second constraint is also created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains. However, this constraint changes when either or both capacity reserve margins and operating reserves are activated. The following constraint enforces that the maximum grid exports and imports must be less than the grid connection capacity (without any policies):

\[\begin{aligned} @@ -169,7 +169,7 @@ & \Theta_{y,z,t} + \Pi_{y,z,t} + \Theta^{CRM,ac}_{y,z,t} + \Pi^{CRM,ac}_{y,z,t} + f^{ac,dis}_{y,z,t} + r^{ac,dis}_{y,z,t} + f^{ac,cha}_{y,z,t} + f^{wind}_{y,z,t} + r^{wind}_{y,z,t} \\ & + \eta^{inverter}_{y,z} \times (\Theta^{CRM,dc}_{y,z,t} + f^{pv}_{y,z,t} + r^{pv}_{y,z,t} + f^{dc,dis}_{y,z,t} + r^{dc,dis}_{y,z,t}) + \frac{\Pi^{CRM,dc}_{y,z,t} + f^{dc,cha}_{y,z,t}}{\eta^{inverter}_{y,z}} \\ & \leq \Delta^{total}_{y,z} \quad \forall y \in \mathcal{VS}, \forall z \in \mathcal{Z}, \forall t \in \mathcal{T} -\end{aligned}\]

The rest of the constraints are dependent upon specific configurable components within the module and are listed below.

source
GenX.vre_stor_capres!Method
vre_stor_capres!(EP::Model, inputs::Dict, setup::Dict)

This function activates capacity reserve margin constraints for co-located VRE and storage resources. The capacity reserve margin formulation for GenX is further elaborated upon in cap_reserve_margin!(). For co-located resources ($y \in \mathcal{VS}$), the available capacity to contribute to the capacity reserve margin is the net injection into the transmission network (which can come from the solar PV, wind, and/or storage component) plus the net virtual injection corresponding to charge held in reserve (which can only come from the storage component), derated by the derating factor. If a capacity reserve margin is modeled, variables for virtual charge DC, $\Pi^{CRM, dc}_{y,z,t}$, virtual charge AC, $\Pi^{CRM, ac}_{y,z,t}$, virtual discharge DC, $\Theta^{CRM, dc}_{y,z,t}$, virtual discharge AC, $\Theta^{CRM, ac}_{o,z,t}$, and virtual state of charge, $\Gamma^{CRM}_{y,z,t}$, are created to represent contributions that a storage device makes to the capacity reserve margin without actually generating power. These represent power that the storage device could have discharged or consumed if called upon to do so, based on its available state of charge. Importantly, a dedicated set of variables and constraints are created to ensure that any virtual contributions to the capacity reserve margin could be made as actual charge/discharge if necessary without affecting system operations in any other timesteps (similar to the standalone storage capacity reserve margin constraints).

If a capacity reserve margin is modeled, then the following constraints track the relationship between the virtual charge variables, $\Pi^{CRM,dc}_{y,z,t}, \Pi^{CRM,ac}_{y,z,t}$, virtual discharge variables, $\Theta^{CRM, dc}_{y,z,t}, \Theta^{CRM, ac}_{y,z,t}$, and the virtual state of charge, $\Gamma^{CRM}_{y,z,t}$, representing the amount of state of charge that must be held in reserve to enable these virtual capacity reserve margin contributions and ensuring that the storage device could deliver its pledged capacity if called upon to do so without affecting its operations in other timesteps. $\Gamma^{CRM}_{y,z,t}$ is tracked similarly to the devices' overall state of charge based on its value in the previous timestep and the virtual charge and discharge in the current timestep. Unlike the regular state of charge, virtual discharge $\Theta^{CRM,dc}_{y,z,t}, \Theta^{CRM,ac}_{y,z,t}$ increases $\Gamma^{CRM}_{y,z,t}$ (as more charge must be held in reserve to support more virtual discharge), and the virtual charge $\Pi^{CRM,dc}_{y,z,t}, \Pi^{CRM,ac}_{y,z,t}$ reduces $\Gamma^{CRM}_{y,z,t}$. Similar to the state of charge constraints in the stor_vre_stor!() function, the first of these two constraints enforces storage inventory balance for interior time steps $(t \in \mathcal{T}^{interior})$, while the second enforces storage balance constraint for the initial time step $(t \in \mathcal{T}^{start})$:

\[\begin{aligned} +\end{aligned}\]

The rest of the constraints are dependent upon specific configurable components within the module and are listed below.

source
GenX.vre_stor_capres!Method
vre_stor_capres!(EP::Model, inputs::Dict, setup::Dict)

This function activates capacity reserve margin constraints for co-located VRE and storage resources. The capacity reserve margin formulation for GenX is further elaborated upon in cap_reserve_margin!(). For co-located resources ($y \in \mathcal{VS}$), the available capacity to contribute to the capacity reserve margin is the net injection into the transmission network (which can come from the solar PV, wind, and/or storage component) plus the net virtual injection corresponding to charge held in reserve (which can only come from the storage component), derated by the derating factor. If a capacity reserve margin is modeled, variables for virtual charge DC, $\Pi^{CRM, dc}_{y,z,t}$, virtual charge AC, $\Pi^{CRM, ac}_{y,z,t}$, virtual discharge DC, $\Theta^{CRM, dc}_{y,z,t}$, virtual discharge AC, $\Theta^{CRM, ac}_{o,z,t}$, and virtual state of charge, $\Gamma^{CRM}_{y,z,t}$, are created to represent contributions that a storage device makes to the capacity reserve margin without actually generating power. These represent power that the storage device could have discharged or consumed if called upon to do so, based on its available state of charge. Importantly, a dedicated set of variables and constraints are created to ensure that any virtual contributions to the capacity reserve margin could be made as actual charge/discharge if necessary without affecting system operations in any other timesteps (similar to the standalone storage capacity reserve margin constraints).

If a capacity reserve margin is modeled, then the following constraints track the relationship between the virtual charge variables, $\Pi^{CRM,dc}_{y,z,t}, \Pi^{CRM,ac}_{y,z,t}$, virtual discharge variables, $\Theta^{CRM, dc}_{y,z,t}, \Theta^{CRM, ac}_{y,z,t}$, and the virtual state of charge, $\Gamma^{CRM}_{y,z,t}$, representing the amount of state of charge that must be held in reserve to enable these virtual capacity reserve margin contributions and ensuring that the storage device could deliver its pledged capacity if called upon to do so without affecting its operations in other timesteps. $\Gamma^{CRM}_{y,z,t}$ is tracked similarly to the devices' overall state of charge based on its value in the previous timestep and the virtual charge and discharge in the current timestep. Unlike the regular state of charge, virtual discharge $\Theta^{CRM,dc}_{y,z,t}, \Theta^{CRM,ac}_{y,z,t}$ increases $\Gamma^{CRM}_{y,z,t}$ (as more charge must be held in reserve to support more virtual discharge), and the virtual charge $\Pi^{CRM,dc}_{y,z,t}, \Pi^{CRM,ac}_{y,z,t}$ reduces $\Gamma^{CRM}_{y,z,t}$. Similar to the state of charge constraints in the stor_vre_stor!() function, the first of these two constraints enforces storage inventory balance for interior time steps $(t \in \mathcal{T}^{interior})$, while the second enforces storage balance constraint for the initial time step $(t \in \mathcal{T}^{start})$:

\[\begin{aligned} & \Gamma^{CRM}_{y,z,t} = \Gamma^{CRM}_{y,z,t-1} + \frac{\Theta^{CRM, dc}_{y,z,t}}{\eta_{y,z}^{discharge,dc}} + \frac{\Theta^{CRM,ac}_{y,z,t}}{\eta_{y,z}^{discharge,ac}} - \eta_{y,z}^{charge,dc} \times \Pi^{CRM,dc}_{y,z,t} - \eta_{y,z}^{charge,ac} \times \Pi^{CRM, ac}_{y,z,t} \\ & - \eta_{y,z}^{loss} \times \Gamma^{CRM}_{y,z,t-1} \quad \forall y \in \mathcal{VS}^{stor}, z \in \mathcal{Z}, t \in \mathcal{T}^{interior}\\ & \Gamma^{CRM}_{y,z,t} = \Gamma^{CRM}_{y,z,t+\tau^{period}-1} + \frac{\Theta^{CRM,dc}_{y,z,t}}{\eta_{y,z}^{discharge,dc}} + \frac{\Theta^{CRM,ac}_{y,z,t}}{\eta_{y,z}^{discharge,ac}} - \eta_{y,z}^{charge,dc} \times \Pi^{CRM,dc}_{y,z,t} - \eta_{y,z}^{charge,ac} \times \Pi^{CRM,ac}_{y,z,t} \\ @@ -188,7 +188,7 @@ & + \frac{\Theta^{CRM,dc}_{y,z,(m-1)\times \tau^{period}+1}}{\eta_{y,z}^{discharge,dc}} + \frac{\Theta^{CRM,ac}_{y,z,(m-1)\times \tau^{period}+1}}{\eta_{y,z}^{discharge,ac}} \\ & - \eta_{y,z}^{charge,dc} \times \Pi^{CRM,dc}_{y,z,(m-1)\times \tau^{period}+1} - \eta_{y,z}^{charge,ac} \times \Pi^{CRM,ac}_{y,z,(m-1)\times \tau^{period}+1} \\ & \forall y \in \mathcal{VS}^{LDES}, z \in \mathcal{Z}, m \in \mathcal{M} -\end{aligned}\]

All other constraints are identical to those used to track the actual state of charge, except with the new variables for the representation of 'virtual' state of charge, build up storage inventory and state of charge at the beginning of each period.

source
GenX.vre_stor_operational_reserves!Method
vre_stor_operational_reserves!(EP::Model, inputs::Dict, setup::Dict)

This function activates either or both frequency regulation and operating reserve options for co-located VRE-storage resources. Co-located VRE and storage resources ($y \in \mathcal{VS}$) have six pairs of auxilary variables to reflect contributions to regulation and reserves when generating electricity from solar PV or wind resources, DC charging and discharging from storage resources, and AC charging and discharging from storage resources. The primary variables ($f_{y,z,t}$ & $r_{y,z,t}$) becomes equal to the sum of these auxilary variables as follows:

\[\begin{aligned} +\end{aligned}\]

All other constraints are identical to those used to track the actual state of charge, except with the new variables for the representation of 'virtual' state of charge, build up storage inventory and state of charge at the beginning of each period.

source
GenX.vre_stor_operational_reserves!Method
vre_stor_operational_reserves!(EP::Model, inputs::Dict, setup::Dict)

This function activates either or both frequency regulation and operating reserve options for co-located VRE-storage resources. Co-located VRE and storage resources ($y \in \mathcal{VS}$) have six pairs of auxilary variables to reflect contributions to regulation and reserves when generating electricity from solar PV or wind resources, DC charging and discharging from storage resources, and AC charging and discharging from storage resources. The primary variables ($f_{y,z,t}$ & $r_{y,z,t}$) becomes equal to the sum of these auxilary variables as follows:

\[\begin{aligned} & f_{y,z,t} = f^{pv}_{y,z,t} + f^{wind}_{y,z,t} + f^{dc,dis}_{y,z,t} + f^{dc,cha}_{y,z,t} + f^{ac,dis}_{y,z,t} + f^{ac,cha}_{y,z,t} & \quad \forall y \in \mathcal{VS}, z \in \mathcal{Z}, t \in \mathcal{T}\\ & r_{y,z,t} = r^{pv}_{y,z,t} + r^{wind}_{y,z,t} + r^{dc,dis}_{y,z,t} + r^{dc,cha}_{y,z,t} + r^{ac,dis}_{y,z,t} + r^{ac,cha}_{y,z,t} & \quad \forall y \in \mathcal{VS}, z \in \mathcal{Z}, t \in \mathcal{T}\\ \end{aligned}\]

Furthermore, the frequency regulation and operating reserves require the maximum contribution from the entire resource to be a specified fraction of the installed grid connection capacity:

\[\begin{aligned} @@ -213,7 +213,7 @@ \end{aligned}\]

Lastly, if the co-located resource has a variable renewable energy component, the solar PV and wind resource can also contribute to frequency regulation reserves and must be greater than zero:

\[\begin{aligned} & \Theta^{pv}_{y,z,t} - f^{pv}_{y,z,t} \geq 0 & \quad \forall y \in \mathcal{VS}^{pv}, z \in \mathcal{Z}, t \in \mathcal{T} \\ & \Theta^{wind}_{y,z,t} - f^{wind}_{y,z,t} \geq 0 & \quad \forall y \in \mathcal{VS}^{wind}, z \in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

source
GenX.wind_vre_stor!Method
wind_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function defines the decision variables, expressions, and constraints for the wind component of each co-located VRE and storage generator.

The total wind capacity of each resource is defined as the sum of the existing wind capacity plus the newly invested wind capacity minus any retired wind capacity:

\[\begin{aligned} +\end{aligned}\]

source
GenX.wind_vre_stor!Method
wind_vre_stor!(EP::Model, inputs::Dict, setup::Dict)

This function defines the decision variables, expressions, and constraints for the wind component of each co-located VRE and storage generator.

The total wind capacity of each resource is defined as the sum of the existing wind capacity plus the newly invested wind capacity minus any retired wind capacity:

\[\begin{aligned} & \Delta^{total, wind}_{y,z} = (\overline{\Delta^{wind}_{y,z}} + \Omega^{wind}_{y,z} - \Delta^{wind}_{y,z}) \quad \forall y \in \mathcal{VS}^{wind}, z \in \mathcal{Z} \end{aligned}\]

One cannot retire more wind capacity than existing wind capacity:

\[\begin{aligned} & \Delta^{wind}_{y,z} \leq \overline{\Delta^{wind}_{y,z}} @@ -233,4 +233,4 @@ & \sum_{y \in \mathcal{VS}^{wind}} \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST, wind}_{y,z} \times \Omega^{wind}_{y,z}) + (\pi^{FOM, wind}_{y,z} \times \Delta^{total,wind}_{y,z}) \right) \\ & + \sum_{y \in \mathcal{VS}^{wind}} \sum_{z \in \mathcal{Z}} \sum_{t \in \mathcal{T}} (\pi^{VOM, wind}_{y,z} \times \Theta^{wind}_{y,z,t}) -\end{aligned}\]

source
GenX.write_vre_storMethod
write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage specific files.

source
GenX.write_vre_stor_capacityMethod
write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage capacities.

source
GenX.write_vre_stor_chargeMethod
write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage charging decision variables/expressions.

source
GenX.write_vre_stor_dischargeMethod
write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage discharging decision variables/expressions.

source
+\end{aligned}\]

source
GenX.write_vre_storMethod
write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage specific files.

source
GenX.write_vre_stor_capacityMethod
write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage capacities.

source
GenX.write_vre_stor_chargeMethod
write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage charging decision variables/expressions.

source
GenX.write_vre_stor_dischargeMethod
write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage discharging decision variables/expressions.

source
diff --git a/previews/PR655/Model_Reference/TDR/index.html b/previews/PR655/Model_Reference/TDR/index.html index f102c1304a..bbb603006b 100644 --- a/previews/PR655/Model_Reference/TDR/index.html +++ b/previews/PR655/Model_Reference/TDR/index.html @@ -1,3 +1,3 @@ -Time-domain Reduction · GenX

Time Domain Reduction (TDR)

GenX.RemoveConstColsFunction
RemoveConstCols(all_profiles, all_col_names)

Remove and store the columns that do not vary during the period.

source
GenX.check_conditionMethod
check_condition(Threshold, R, OldColNames, ScalingMethod, TimestepsPerRepPeriod)

Check whether the greatest Euclidean deviation in the input data and the clustered representation is within a given proportion of the "maximum" possible deviation.

(1 for Normalization covers 100%, 4 for Standardization covers ~95%)

source
GenX.cluster_inputsFunction
cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false; random=true)

Use kmeans or kmedoids to cluster raw demand profiles and resource capacity factor profiles into representative periods. Use Extreme Periods to capture noteworthy periods or periods with notably poor fits.

In Demand_data.csv, include the following:

  • Timesteps_per_Rep_Period - Typically 168 timesteps (e.g., hours) per period, this designates the length of each representative period.
  • UseExtremePeriods - Either 1 or 0, this designates whether or not to include outliers (by performance or demand/resource extreme) as their own representative periods. This setting automatically includes the periods with maximum demand, minimum solar cf and minimum wind cf as extreme periods.
  • ClusterMethod - Either 'kmeans' or 'kmedoids', this designates the method used to cluster periods and determine each point's representative period.
  • ScalingMethod - Either 'N' or 'S', this designates directs the module to normalize ([0,1]) or standardize (mean 0, variance 1) the input data.
  • MinPeriods - The minimum number of periods used to represent the input data. If using UseExtremePeriods, this must be at least three. If IterativelyAddPeriods if off, this will be the total number of periods.
  • MaxPeriods - The maximum number of periods - both clustered periods and extreme periods - that may be used to represent the input data.
  • IterativelyAddPeriods - Either 1 or 0, this designates whether or not to add periods until the error threshold between input data and represented data is met or the maximum number of periods is reached.
  • Threshold - Iterative period addition will end if the period farthest (Euclidean Distance) from its representative period is within this percentage of the total possible error (for normalization) or ~95% of the total possible error (for standardization). E.g., for a threshold of 0.01, every period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the max number of periods is reached).
  • IterateMethod - Either 'cluster' or 'extreme', this designates whether to add clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.
  • nReps - The number of times to repeat each kmeans/kmedoids clustering at the same setting.
  • DemandWeight - Default 1, this is an optional multiplier on demand columns in order to prioritize better fits for demand profiles over resource capacity factor profiles.
  • WeightTotal - Default 8760, the sum to which the relative weights of representative periods will be scaled.
  • ClusterFuelPrices - Either 1 or 0, this indicates whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data_clustered.csv with reshaped fuel prices based on the number and size of the representative weeks, assuming a constant time series of fuel prices with length equal to the number of timesteps in the raw input data.
  • MultiStageConcatenate - (Only considered if MultiStage = 1 in genx_settings.yml) If 1, this designates that the model should time domain reduce the input data of all model stages together. Else if 0, [still in development] the model will time domain reduce only the first stage and will apply the periods of each other model stage to this set of representative periods by closest Eucliden distance.

For co-located VRE-STOR resources, all capacity factors must be in the Generatorsvariability.csv file in addition to separate Vreandstorsolarvariability.csv and Vreandstorwind_variability.csv files. The co-located solar PV and wind profiles for co-located resources will be separated into different CSV files to be read by loading the inputs after the clustering of the inputs has occurred.

source
GenX.get_absolute_extremeMethod
get_absolute_extreme(DF, statKey, col_names, ConstCols)

Get the period index of the single timestep with the minimum or maximum demand or capacity factor.

source
GenX.get_demand_multipliersFunction
get_demand_multipliers(ClusterOutputData, ModifiedData, M, W, DemandCols, TimestepsPerRepPeriod, NewColNames, NClusters, Ncols)

Get multipliers to linearly scale clustered demand profiles L zone-wise such that their weighted sum equals the original zonal total demand. Scale demand profiles later using these multipliers in order to ensure that a copy of the original demand is kept for validation.

Find $k_z$ such that:

\[\sum_{i \in I} L_{i,z} = \sum_{t \in T, m \in M} C_{t,m,z} \cdot \frac{w_m}{T} \cdot k_z \: \: \: \forall z \in Z\]

where $Z$ is the set of zones, $I$ is the full time domain, $T$ is the length of one period (e.g., 168 for one week in hours), $M$ is the set of representative periods, $L_{i,z}$ is the original zonal demand profile over time (hour) index $i$, $C_{i,m,z}$ is the demand in timestep $i$ for representative period $m$ in zone $z$, $w_m$ is the weight of the representative period equal to the total number of hours that one hour in representative period $m$ represents in the original profile, and $k_z$ is the zonal demand multiplier returned by the function.

source
GenX.get_extreme_periodFunction
get_extreme_period(DF, GDF, profKey, typeKey, statKey,
-   ConstCols, demand_col_names, solar_col_names, wind_col_names)

Identify extreme week by specification of profile type (Demand, PV, Wind), measurement type (absolute (timestep with min/max value) vs. integral (period with min/max summed value)), and statistic (minimum or maximum). I.e., the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select "Demand", "System, "Absolute, and "Max".

source
GenX.get_integral_extremeMethod
get_integral_extreme(GDF, statKey, col_names, ConstCols)

Get the period index with the minimum or maximum demand or capacity factor summed over the period.

source
GenX.get_worst_period_idxMethod
get_worst_period_idx(R)

Get the index of the period that is farthest from its representative period by Euclidean distance.

source
GenX.parse_dataMethod
parse_data(myinputs)

Get demand, solar, wind, and other curves from the input data.

source
GenX.rmse_scoreMethod
rmse_score(y_true, y_pred)

Calculates Root Mean Square Error.

\[RMSE = \sqrt{\frac{1}{n}\Sigma_{i=1}^{n}{\Big(\frac{d_i -f_i}{\sigma_i}\Big)^2}}\]

source
GenX.scale_weightsFunction
scale_weights(W, H)

Linearly scale weights W such that they sum to the desired number of timesteps (hours) H.

\[w_j \leftarrow H \cdot \frac{w_j}{\sum_i w_i} \: \: \: \forall w_j \in W\]

source
GenX.run_timedomainreduction!Function

Run the GenX time domain reduction on the given case folder

case - folder for the case stage_id - possibly something to do with MultiStage verbose - print extra outputs

This function overwrites the time-domain-reduced inputs if they already exist.

source
+Time-domain Reduction · GenX

Time Domain Reduction (TDR)

GenX.RemoveConstColsFunction
RemoveConstCols(all_profiles, all_col_names)

Remove and store the columns that do not vary during the period.

source
GenX.check_conditionMethod
check_condition(Threshold, R, OldColNames, ScalingMethod, TimestepsPerRepPeriod)

Check whether the greatest Euclidean deviation in the input data and the clustered representation is within a given proportion of the "maximum" possible deviation.

(1 for Normalization covers 100%, 4 for Standardization covers ~95%)

source
GenX.cluster_inputsFunction
cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false; random=true)

Use kmeans or kmedoids to cluster raw demand profiles and resource capacity factor profiles into representative periods. Use Extreme Periods to capture noteworthy periods or periods with notably poor fits.

In Demand_data.csv, include the following:

  • Timesteps_per_Rep_Period - Typically 168 timesteps (e.g., hours) per period, this designates the length of each representative period.
  • UseExtremePeriods - Either 1 or 0, this designates whether or not to include outliers (by performance or demand/resource extreme) as their own representative periods. This setting automatically includes the periods with maximum demand, minimum solar cf and minimum wind cf as extreme periods.
  • ClusterMethod - Either 'kmeans' or 'kmedoids', this designates the method used to cluster periods and determine each point's representative period.
  • ScalingMethod - Either 'N' or 'S', this designates directs the module to normalize ([0,1]) or standardize (mean 0, variance 1) the input data.
  • MinPeriods - The minimum number of periods used to represent the input data. If using UseExtremePeriods, this must be at least three. If IterativelyAddPeriods if off, this will be the total number of periods.
  • MaxPeriods - The maximum number of periods - both clustered periods and extreme periods - that may be used to represent the input data.
  • IterativelyAddPeriods - Either 1 or 0, this designates whether or not to add periods until the error threshold between input data and represented data is met or the maximum number of periods is reached.
  • Threshold - Iterative period addition will end if the period farthest (Euclidean Distance) from its representative period is within this percentage of the total possible error (for normalization) or ~95% of the total possible error (for standardization). E.g., for a threshold of 0.01, every period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the max number of periods is reached).
  • IterateMethod - Either 'cluster' or 'extreme', this designates whether to add clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.
  • nReps - The number of times to repeat each kmeans/kmedoids clustering at the same setting.
  • DemandWeight - Default 1, this is an optional multiplier on demand columns in order to prioritize better fits for demand profiles over resource capacity factor profiles.
  • WeightTotal - Default 8760, the sum to which the relative weights of representative periods will be scaled.
  • ClusterFuelPrices - Either 1 or 0, this indicates whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data_clustered.csv with reshaped fuel prices based on the number and size of the representative weeks, assuming a constant time series of fuel prices with length equal to the number of timesteps in the raw input data.
  • MultiStageConcatenate - (Only considered if MultiStage = 1 in genx_settings.yml) If 1, this designates that the model should time domain reduce the input data of all model stages together. Else if 0, [still in development] the model will time domain reduce only the first stage and will apply the periods of each other model stage to this set of representative periods by closest Eucliden distance.

For co-located VRE-STOR resources, all capacity factors must be in the Generatorsvariability.csv file in addition to separate Vreandstorsolarvariability.csv and Vreandstorwind_variability.csv files. The co-located solar PV and wind profiles for co-located resources will be separated into different CSV files to be read by loading the inputs after the clustering of the inputs has occurred.

source
GenX.get_absolute_extremeMethod
get_absolute_extreme(DF, statKey, col_names, ConstCols)

Get the period index of the single timestep with the minimum or maximum demand or capacity factor.

source
GenX.get_demand_multipliersFunction
get_demand_multipliers(ClusterOutputData, ModifiedData, M, W, DemandCols, TimestepsPerRepPeriod, NewColNames, NClusters, Ncols)

Get multipliers to linearly scale clustered demand profiles L zone-wise such that their weighted sum equals the original zonal total demand. Scale demand profiles later using these multipliers in order to ensure that a copy of the original demand is kept for validation.

Find $k_z$ such that:

\[\sum_{i \in I} L_{i,z} = \sum_{t \in T, m \in M} C_{t,m,z} \cdot \frac{w_m}{T} \cdot k_z \: \: \: \forall z \in Z\]

where $Z$ is the set of zones, $I$ is the full time domain, $T$ is the length of one period (e.g., 168 for one week in hours), $M$ is the set of representative periods, $L_{i,z}$ is the original zonal demand profile over time (hour) index $i$, $C_{i,m,z}$ is the demand in timestep $i$ for representative period $m$ in zone $z$, $w_m$ is the weight of the representative period equal to the total number of hours that one hour in representative period $m$ represents in the original profile, and $k_z$ is the zonal demand multiplier returned by the function.

source
GenX.get_extreme_periodFunction
get_extreme_period(DF, GDF, profKey, typeKey, statKey,
+   ConstCols, demand_col_names, solar_col_names, wind_col_names)

Identify extreme week by specification of profile type (Demand, PV, Wind), measurement type (absolute (timestep with min/max value) vs. integral (period with min/max summed value)), and statistic (minimum or maximum). I.e., the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select "Demand", "System, "Absolute, and "Max".

source
GenX.get_integral_extremeMethod
get_integral_extreme(GDF, statKey, col_names, ConstCols)

Get the period index with the minimum or maximum demand or capacity factor summed over the period.

source
GenX.get_worst_period_idxMethod
get_worst_period_idx(R)

Get the index of the period that is farthest from its representative period by Euclidean distance.

source
GenX.parse_dataMethod
parse_data(myinputs)

Get demand, solar, wind, and other curves from the input data.

source
GenX.rmse_scoreMethod
rmse_score(y_true, y_pred)

Calculates Root Mean Square Error.

\[RMSE = \sqrt{\frac{1}{n}\Sigma_{i=1}^{n}{\Big(\frac{d_i -f_i}{\sigma_i}\Big)^2}}\]

source
GenX.scale_weightsFunction
scale_weights(W, H)

Linearly scale weights W such that they sum to the desired number of timesteps (hours) H.

\[w_j \leftarrow H \cdot \frac{w_j}{\sum_i w_i} \: \: \: \forall w_j \in W\]

source
GenX.run_timedomainreduction!Function

Run the GenX time domain reduction on the given case folder

case - folder for the case stage_id - possibly something to do with MultiStage verbose - print extra outputs

This function overwrites the time-domain-reduced inputs if they already exist.

source
diff --git a/previews/PR655/Model_Reference/core/index.html b/previews/PR655/Model_Reference/core/index.html index 591b8efaff..f4ec4104a6 100644 --- a/previews/PR655/Model_Reference/core/index.html +++ b/previews/PR655/Model_Reference/core/index.html @@ -2,7 +2,7 @@ Core · GenX

Core

Discharge

GenX.discharge!Method
discharge!(EP::Model, inputs::Dict, setup::Dict)

This module defines the power decision variable $\Theta_{y,t} \forall y \in \mathcal{G}, t \in \mathcal{T}$, representing energy injected into the grid by resource $y$ by at time period $t$. This module additionally defines contributions to the objective function from variable costs of generation (variable O&M) from all resources $y \in \mathcal{G}$ over all time periods $t \in \mathcal{T}$:

\[\begin{aligned} Obj_{Var\_gen} = \sum_{y \in \mathcal{G} } \sum_{t \in \mathcal{T}}\omega_{t}\times(\pi^{VOM}_{y})\times \Theta_{y,t} -\end{aligned}\]

source
GenX.investment_discharge!Method
investment_discharge!(EP::Model, inputs::Dict, setup::Dict)

This function defines the expressions and constraints keeping track of total available power generation/discharge capacity across all resources as well as constraints on capacity retirements. The total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity. Note for storage and co-located resources, additional energy and charge power capacity decisions and constraints are defined in the storage and co-located VRE and storage module respectively.

\[\begin{aligned} +\end{aligned}\]

source
GenX.investment_discharge!Method
investment_discharge!(EP::Model, inputs::Dict, setup::Dict)

This function defines the expressions and constraints keeping track of total available power generation/discharge capacity across all resources as well as constraints on capacity retirements. The total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity. Note for storage and co-located resources, additional energy and charge power capacity decisions and constraints are defined in the storage and co-located VRE and storage module respectively.

\[\begin{aligned} & \Delta^{total}_{y,z} =(\overline{\Delta_{y,z}}+\Omega_{y,z}-\Delta_{y,z}) \forall y \in \mathcal{G}, z \in \mathcal{Z} \end{aligned}\]

One cannot retire more capacity than existing capacity.

\[\begin{aligned} &\Delta_{y,z} \leq \overline{\Delta_{y,z}} @@ -16,7 +16,7 @@ & \sum_{y \in \mathcal{G} } \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST}_{y,z} \times \overline{\Omega}^{size}_{y,z} \times \Omega_{y,z}) + (\pi^{FOM}_{y,z} \times \overline{\Omega}^{size}_{y,z} \times \Delta^{total}_{y,z})\right) -\end{aligned}\]

source
GenX.write_multi_stage_capacities_dischargeMethod
write_multi_stage_capacities_discharge(outpath::String, settings_d::Dict)

This function writes the file capacities_multi_stage.csv to the Results directory. This file contains starting resource capacities from the first model stage and end resource capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_virtual_dischargeMethod
write_virtual_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the "virtual" discharge of each storage technology. Virtual discharge is used to allow storage resources to contribute to the capacity reserve margin without actually discharging.

source

Non-served Energy

GenX.non_served_energy!Method
non_served_energy!(EP::Model, inputs::Dict, setup::Dict)

This function defines the non-served energy/curtailed demand decision variable $\Lambda_{s,t,z} \forall s \in \mathcal{S}, \forall t \in \mathcal{T}, z \in \mathcal{Z}$, representing the total amount of demand curtailed in demand segment $s$ at time period $t$ in zone $z$. The first segment of non-served energy, $s=1$, is used to denote the cost of involuntary demand curtailment (e.g. emergency load shedding or rolling blackouts), specified as the value of $n_{1}^{slope}$. Additional segments, $s \geq 2$ can be used to specify a segment-wise approximation of a price elastic demand curve, or segments of price-responsive curtailable demands (aka demand response). Each segment denotes a price/cost at which the segment of demand is willing to curtail consumption, $n_{s}^{slope}$, representing the marginal willingness to pay for electricity of this segment of demand (or opportunity cost incurred when demand is not served) and a maximum quantity of demand in this segment, $n_{s}^{size}$, specified as a share of demand in each zone in each time step, $D_{t,z}.$ Note that the current implementation assumes demand segments are an equal share of hourly demand in all zones. This function defines contributions to the objective function from the cost of non-served energy/curtailed demand from all demand curtailment segments $s \in \mathcal{S}$ over all time periods $t \in \mathcal{T}$ and all zones $z \in \mathcal{Z}$:

\[\begin{aligned} +\end{aligned}\]

source
GenX.write_multi_stage_capacities_dischargeMethod
write_multi_stage_capacities_discharge(outpath::String, settings_d::Dict)

This function writes the file capacities_multi_stage.csv to the Results directory. This file contains starting resource capacities from the first model stage and end resource capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_virtual_dischargeMethod
write_virtual_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the "virtual" discharge of each storage technology. Virtual discharge is used to allow storage resources to contribute to the capacity reserve margin without actually discharging.

source

Non-served Energy

GenX.non_served_energy!Method
non_served_energy!(EP::Model, inputs::Dict, setup::Dict)

This function defines the non-served energy/curtailed demand decision variable $\Lambda_{s,t,z} \forall s \in \mathcal{S}, \forall t \in \mathcal{T}, z \in \mathcal{Z}$, representing the total amount of demand curtailed in demand segment $s$ at time period $t$ in zone $z$. The first segment of non-served energy, $s=1$, is used to denote the cost of involuntary demand curtailment (e.g. emergency load shedding or rolling blackouts), specified as the value of $n_{1}^{slope}$. Additional segments, $s \geq 2$ can be used to specify a segment-wise approximation of a price elastic demand curve, or segments of price-responsive curtailable demands (aka demand response). Each segment denotes a price/cost at which the segment of demand is willing to curtail consumption, $n_{s}^{slope}$, representing the marginal willingness to pay for electricity of this segment of demand (or opportunity cost incurred when demand is not served) and a maximum quantity of demand in this segment, $n_{s}^{size}$, specified as a share of demand in each zone in each time step, $D_{t,z}.$ Note that the current implementation assumes demand segments are an equal share of hourly demand in all zones. This function defines contributions to the objective function from the cost of non-served energy/curtailed demand from all demand curtailment segments $s \in \mathcal{S}$ over all time periods $t \in \mathcal{T}$ and all zones $z \in \mathcal{Z}$:

\[\begin{aligned} Obj_{NSE} = \sum_{s \in \mathcal{S} } \sum_{t \in \mathcal{T}} \sum_{z \in \mathcal{Z}}\omega_{t} \times n_{s}^{slope} \times \Lambda_{s,t,z} \end{aligned}\]

Contributions to the power balance expression from non-served energy/curtailed demand from each demand segment $s \in \mathcal{S}$ are also defined as:

\[\begin{aligned} @@ -29,7 +29,7 @@ \end{aligned}\]

Additionally, total demand curtailed in each time step cannot exceed total demand:

\[\begin{aligned} \sum_{s \in \mathcal{S} } \Lambda_{s,t,z} \leq D_{t,z} \hspace{4 cm} \forall t \in \mathcal{T}, z\in \mathcal{Z} -\end{aligned}\]

source

Operational Reserves

GenX.load_operational_reserves!Method
load_operational_reserves!(setup::Dict,path::AbstractString, inputs::Dict)

Read input parameters related to frequency regulation and operating reserve requirements

source
GenX.operational_reserves!Method
operational_reserves!(EP::Model, inputs::Dict, setup::Dict)

This function sets up reserve decisions and constraints, using the operationalreservescore()and operational_reserves_contingency() functions.

source
GenX.operational_reserves_contingency!Method
operational_reserves_contingency!(EP::Model, inputs::Dict, setup::Dict)

This function establishes several different versions of contingency reserve requirement expression, $CONTINGENCY$ used in the operationalreservescore() function below.

Contingency operational reserves represent requirements for upward ramping capability within a specified time frame to compensated for forced outages or unplanned failures of generators or transmission lines (e.g. N-1 contingencies).

There are three options for the $Contingency$ expression, depending on user settings: 1. a static contingency, in which the contingency requirement is set based on a fixed value (in MW) specified in the '''Operational_reserves.csv''' input file; 2. a dynamic contingency based on installed capacity decisions, in which the largest 'installed' generator is used to determine the contingency requirement for all time periods; and 3. dynamic unit commitment based contingency, in which the largest 'committed' generator in any time period is used to determine the contingency requirement in that time period.

Note that the two dynamic contigencies are only available if unit commitment is being modeled.

Static contingency Option 1 (static contingency) is expressed by the following constraint:

\[\begin{aligned} +\end{aligned}\]

source

Operational Reserves

GenX.load_operational_reserves!Method
load_operational_reserves!(setup::Dict,path::AbstractString, inputs::Dict)

Read input parameters related to frequency regulation and operating reserve requirements

source
GenX.operational_reserves!Method
operational_reserves!(EP::Model, inputs::Dict, setup::Dict)

This function sets up reserve decisions and constraints, using the operationalreservescore()and operational_reserves_contingency() functions.

source
GenX.operational_reserves_contingency!Method
operational_reserves_contingency!(EP::Model, inputs::Dict, setup::Dict)

This function establishes several different versions of contingency reserve requirement expression, $CONTINGENCY$ used in the operationalreservescore() function below.

Contingency operational reserves represent requirements for upward ramping capability within a specified time frame to compensated for forced outages or unplanned failures of generators or transmission lines (e.g. N-1 contingencies).

There are three options for the $Contingency$ expression, depending on user settings: 1. a static contingency, in which the contingency requirement is set based on a fixed value (in MW) specified in the '''Operational_reserves.csv''' input file; 2. a dynamic contingency based on installed capacity decisions, in which the largest 'installed' generator is used to determine the contingency requirement for all time periods; and 3. dynamic unit commitment based contingency, in which the largest 'committed' generator in any time period is used to determine the contingency requirement in that time period.

Note that the two dynamic contigencies are only available if unit commitment is being modeled.

Static contingency Option 1 (static contingency) is expressed by the following constraint:

\[\begin{aligned} Contingency = \epsilon^{contingency} \end{aligned}\]

where $\epsilon^{contingency}$ is static contingency requirement in MWs.

Dynamic capacity-based contingency Option 2 (dynamic capacity-based contingency) is expressed by the following constraints:

\[\begin{aligned} &Contingency \geq \Omega^{size}_{y,z} \times \alpha^{Contingency,Aux}_{y,z} & \forall y \in \mathcal{UC}, z \in \mathcal{Z}\\ @@ -39,7 +39,7 @@ & Contingency \geq \Omega^{size}_{y,z} \times Contingency\_Aux_{y,z,t} & \forall y \in \mathcal{UC}, z \in \mathcal{Z}\\ & Contingency\_Aux_{y,z,t} \leq \nu_{y,z,t} & \forall y \in \mathcal{UC}, z \in \mathcal{Z}\\ & Contingency\_Aux_{y,z,t} \geq M_y \times \nu_{y,z,t} & \forall y \in \mathcal{UC}, z \in \mathcal{Z}\\ -\end{aligned}\]

where $M_y$ is a `big M' constant equal to the largest possible capacity that can be installed for generation cluster $y$, and $Contingency\_Aux_{y,z,t} \in [0,1]$ is a binary auxiliary variable that is forced by the second and third equations above to be 1 if the commitment state for that generation cluster $\nu_{y,z,t} > 0$ for any generator $y \in \mathcal{UC}$ and zone $z$ and time period $t$, and can be 0 otherwise. Note that this dynamic commitment-based contingency can only be specified if discrete unit commitment decisions are used (e.g. it will not work if relaxed unit commitment is used).

source
GenX.operational_reserves_core!Method
operational_reserves_core!(EP::Model, inputs::Dict, setup::Dict)

This function creates decision variables related to frequency regulation and reserves provision and constraints setting overall system requirements for regulation and operating reserves.

Regulation and reserves decisions $f_{y,t,z} \geq 0$ is the contribution of generation or storage resource $y \in Y$ in time $t \in T$ and zone $z \in Z$ to frequency regulation

\[r_{y,t,z} \geq 0\]

is the contribution of generation or storage resource $y \in Y$ in time $t \in T$ and zone $z \in Z$ to operating reserves up

We assume frequency regulation is symmetric (provided in equal quantity towards both upwards and downwards regulation). To reduce computational complexity, operating reserves are only modeled in the upwards direction, as downwards reserves requirements are rarely binding in practice.

Storage resources ($y \in \mathcal{O}$) have two pairs of auxilary variables to reflect contributions to regulation and reserves when charging and discharging, where the primary variables ($f_{y,z,t}$ \& $r_{y,z,t}$) becomes equal to sum of these auxilary variables.

Co-located VRE-STOR resources are described further in the reserves function for colocated VRE and storage resources (vre_stor_operational_reserves!()).

Unmet operating reserves

\[unmet\_rsv_{t} \geq 0\]

denotes any shortfall in provision of operating reserves during each time period $t \in T$

There is a penalty $C^{rsv}$ added to the objective function to penalize reserve shortfalls, equal to:

\[\begin{aligned} +\end{aligned}\]

where $M_y$ is a `big M' constant equal to the largest possible capacity that can be installed for generation cluster $y$, and $Contingency\_Aux_{y,z,t} \in [0,1]$ is a binary auxiliary variable that is forced by the second and third equations above to be 1 if the commitment state for that generation cluster $\nu_{y,z,t} > 0$ for any generator $y \in \mathcal{UC}$ and zone $z$ and time period $t$, and can be 0 otherwise. Note that this dynamic commitment-based contingency can only be specified if discrete unit commitment decisions are used (e.g. it will not work if relaxed unit commitment is used).

source
GenX.operational_reserves_core!Method
operational_reserves_core!(EP::Model, inputs::Dict, setup::Dict)

This function creates decision variables related to frequency regulation and reserves provision and constraints setting overall system requirements for regulation and operating reserves.

Regulation and reserves decisions $f_{y,t,z} \geq 0$ is the contribution of generation or storage resource $y \in Y$ in time $t \in T$ and zone $z \in Z$ to frequency regulation

\[r_{y,t,z} \geq 0\]

is the contribution of generation or storage resource $y \in Y$ in time $t \in T$ and zone $z \in Z$ to operating reserves up

We assume frequency regulation is symmetric (provided in equal quantity towards both upwards and downwards regulation). To reduce computational complexity, operating reserves are only modeled in the upwards direction, as downwards reserves requirements are rarely binding in practice.

Storage resources ($y \in \mathcal{O}$) have two pairs of auxilary variables to reflect contributions to regulation and reserves when charging and discharging, where the primary variables ($f_{y,z,t}$ \& $r_{y,z,t}$) becomes equal to sum of these auxilary variables.

Co-located VRE-STOR resources are described further in the reserves function for colocated VRE and storage resources (vre_stor_operational_reserves!()).

Unmet operating reserves

\[unmet\_rsv_{t} \geq 0\]

denotes any shortfall in provision of operating reserves during each time period $t \in T$

There is a penalty $C^{rsv}$ added to the objective function to penalize reserve shortfalls, equal to:

\[\begin{aligned} C^{rvs} = \sum_{t \in T} \omega_t \times unmet\_rsv_{t} \end{aligned}\]

Frequency regulation requirements

Total requirements for frequency regulation (aka primary reserves) in each time step $t$ are specified as fractions of hourly demand (to reflect demand forecast errors) and variable renewable avaialblity in the time step (to reflect wind and solar forecast errors).

\[\begin{aligned} & \sum_{y \in Y, z \in Z} f_{y,t,z} \geq \epsilon^{demand}_{reg} \times \sum_{z \in Z} \mathcal{D}_{z,t} + \epsilon^{vre}_{reg} \times (\sum_{z \in Z} \rho^{max}_{y,z,t} \times \Delta^{\text{total}}_{y,z} \\ @@ -47,14 +47,14 @@ \end{aligned}\]

where $\mathcal{D}_{z,t}$ is the forecasted electricity demand in zone $z$ at time $t$ (before any demand flexibility); $\rho^{max}_{y,z,t}$ is the forecasted capacity factor for standalone variable renewable resources $y \in VRE$ and zone $z$ in time step $t$; $\rho^{max,pv}_{y,z,t}$ is the forecasted capacity factor for co-located solar PV resources $y \in \mathcal{VS}^{pv}$ and zone $z$ in time step $t$; $\rho^{max,wind}_{y,z,t}$ is the forecasted capacity factor for co-located wind resources $y \in \mathcal{VS}^{pv}$ and zone $z$ in time step $t$; $\Delta^{\text{total,pv}}_{y,z}$ is the total installed capacity of co-located solar PV resources $y \in \mathcal{VS}^{pv}$ and zone $z$; $\Delta^{\text{total,wind}}_{y,z}$ is the total installed capacity of co-located wind resources $y \in \mathcal{VS}^{wind}$ and zone $z$; and $\epsilon^{demand}_{reg}$ and $\epsilon^{vre}_{reg}$ are parameters specifying the required frequency regulation as a fraction of forecasted demand and variable renewable generation.

Operating reserve requirements

Total requirements for operating reserves in the upward direction (aka spinning reserves or contingency reserces or secondary reserves) in each time step $t$ are specified as fractions of time step's demand (to reflect demand forecast errors) and variable renewable avaialblity in the time step (to reflect wind and solar forecast errors) plus the largest planning contingency (e.g. potential forced generation outage).

\[\begin{aligned} & \sum_{y \in Y, z \in Z} r_{y,z,t} + r^{unmet}_{t} \geq \epsilon^{demand}_{rsv} \times \sum_{z \in Z} \mathcal{D}_{z,t} + \epsilon^{vre}_{rsv} \times (\sum_{z \in Z} \rho^{max}_{y,z,t} \times \Delta^{\text{total}}_{y,z} \\ & + \sum_{z \in Z} \rho^{max,pv}_{y,z,t} \times \Delta^{\text{total,pv}}_{y,z} + \sum_{z \in Z} \rho^{max,wind}_{y,z,t} \times \Delta^{\text{total,wind}}_{y,z}) + Contingency \quad \forall t \in T -\end{aligned}\]

where $\mathcal{D}_{z,t}$ is the forecasted electricity demand in zone $z$ at time $t$ (before any demand flexibility); $\rho^{max}_{y,z,t}$ is the forecasted capacity factor for standalone variable renewable resources $y \in VRE$ and zone $z$ in time step $t$; $\rho^{max,pv}_{y,z,t}$ is the forecasted capacity factor for co-located solar PV resources $y \in \mathcal{VS}^{pv}$ and zone $z$ in time step $t$; $\rho^{max,wind}_{y,z,t}$ is the forecasted capacity factor for co-located wind resources $y \in \mathcal{VS}^{wind}$ and zone $z$ in time step $t$; $\Delta^{\text{total}}_{y,z}$ is the total installed capacity of standalone variable renewable resources $y \in VRE$ and zone $z$; $\Delta^{\text{total,pv}}_{y,z}$ is the total installed capacity of co-located solar PV resources $y \in \mathcal{VS}^{pv}$ and zone $z$; $\Delta^{\text{total,wind}}_{y,z}$ is the total installed capacity of co-located wind resources $y \in \mathcal{VS}^{wind}$ and zone $z$; and $\epsilon^{demand}_{rsv}$ and $\epsilon^{vre}_{rsv}$ are parameters specifying the required contingency reserves as a fraction of forecasted demand and variable renewable generation. $Contingency$ is an expression defined in the operational_reserves_contingency!() function meant to represent the largest N-1 contingency (unplanned generator outage) that the system operator must carry operating reserves to cover and depends on how the user wishes to specify contingency requirements.

source

Transmission

GenX.dcopf_transmission!Method
function dcopf_transmission!(EP::Model, inputs::Dict, setup::Dict)

The addtional constraints imposed upon the line flows in the case of DC-OPF are as follows: For the definition of the line flows, in terms of the voltage phase angles:

\[\begin{aligned} +\end{aligned}\]

where $\mathcal{D}_{z,t}$ is the forecasted electricity demand in zone $z$ at time $t$ (before any demand flexibility); $\rho^{max}_{y,z,t}$ is the forecasted capacity factor for standalone variable renewable resources $y \in VRE$ and zone $z$ in time step $t$; $\rho^{max,pv}_{y,z,t}$ is the forecasted capacity factor for co-located solar PV resources $y \in \mathcal{VS}^{pv}$ and zone $z$ in time step $t$; $\rho^{max,wind}_{y,z,t}$ is the forecasted capacity factor for co-located wind resources $y \in \mathcal{VS}^{wind}$ and zone $z$ in time step $t$; $\Delta^{\text{total}}_{y,z}$ is the total installed capacity of standalone variable renewable resources $y \in VRE$ and zone $z$; $\Delta^{\text{total,pv}}_{y,z}$ is the total installed capacity of co-located solar PV resources $y \in \mathcal{VS}^{pv}$ and zone $z$; $\Delta^{\text{total,wind}}_{y,z}$ is the total installed capacity of co-located wind resources $y \in \mathcal{VS}^{wind}$ and zone $z$; and $\epsilon^{demand}_{rsv}$ and $\epsilon^{vre}_{rsv}$ are parameters specifying the required contingency reserves as a fraction of forecasted demand and variable renewable generation. $Contingency$ is an expression defined in the operational_reserves_contingency!() function meant to represent the largest N-1 contingency (unplanned generator outage) that the system operator must carry operating reserves to cover and depends on how the user wishes to specify contingency requirements.

source

Transmission

GenX.dcopf_transmission!Method
function dcopf_transmission!(EP::Model, inputs::Dict, setup::Dict)

The addtional constraints imposed upon the line flows in the case of DC-OPF are as follows: For the definition of the line flows, in terms of the voltage phase angles:

\[\begin{aligned} & \Phi_{l,t}=\mathcal{B}_{l} \times (\sum_{z\in \mathcal{Z}}{(\varphi^{map}_{l,z} \times \theta_{z,t})}) \quad \forall l \in \mathcal{L}, \; \forall t \in \mathcal{T}\\ \end{aligned}\]

For imposing the constraint of maximum allowed voltage phase angle difference across lines:

\[\begin{aligned} & \sum_{z\in \mathcal{Z}}{(\varphi^{map}_{l,z} \times \theta_{z,t})} \leq \Delta \theta^{\max}_{l} \quad \forall l \in \mathcal{L}, \forall t \in \mathcal{T}\\ & \sum_{z\in \mathcal{Z}}{(\varphi^{map}_{l,z} \times \theta_{z,t})} \geq -\Delta \theta^{\max}_{l} \quad \forall l \in \mathcal{L}, \forall t \in \mathcal{T}\\ \end{aligned}\]

Finally, we enforce the reference voltage phase angle constraint:

\[\begin{aligned} \theta_{1,t} = 0 \quad \forall t \in \mathcal{T} -\end{aligned}\]

source
GenX.investment_transmission!Method
function investment_transmission!(EP::Model, inputs::Dict, setup::Dict)
     The function model transmission expansion and adds transmission reinforcement or construction costs to the objective function. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, $pi^{TCAP}_{l}$, times the additional transmission capacity variable, $\bigtriangleup\varphi^{cap}_{l}$.
     ```math
     \begin{aligned}
@@ -72,7 +72,7 @@
     The additional transmission capacity, $\bigtriangleup\varphi^{cap}_{l} $, is constrained by a maximum allowed reinforcement, $\overline{\bigtriangleup\varphi^{cap}_{l}}$, for each line $l \in \mathcal{E}$.
     \begin{aligned}
     & \bigtriangleup\varphi^{cap}_{l}  \leq \overline{\bigtriangleup\varphi^{cap}_{l}}, &\quad \forall l \in \mathcal{E}
-    \end{aligned}
source
GenX.transmission!Method
transmission!(EP::Model, inputs::Dict, setup::Dict)

This function establishes decisions, expressions, and constraints related to transmission power flows between model zones and associated transmission losses (if modeled).

Power flow and transmission loss terms are also added to the power balance constraint for each zone:

\[\begin{aligned} + \end{aligned}

source
GenX.transmission!Method
transmission!(EP::Model, inputs::Dict, setup::Dict)

This function establishes decisions, expressions, and constraints related to transmission power flows between model zones and associated transmission losses (if modeled).

Power flow and transmission loss terms are also added to the power balance constraint for each zone:

\[\begin{aligned} & - \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \Phi_{l,t})} - \frac{1}{2} \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \beta_{l,t}(\cdot))} \end{aligned}\]

Power flows, $\Phi_{l,t}$, on each line $l$ into or out of a zone (defined by the network map $\varphi^{map}_{l,z}$), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign is used for this term. Losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function $\beta_{l,t}(\cdot)$ will depend on the configuration used to model losses (see below). Accounting for Transmission Between Zones Power flow, $\Phi_{l,t}$, on each line (or more likely a `path' aggregating flows across multiple parallel lines) is constrained to be less than or equal to the line's power transfer capacity, $\varphi^{cap}_{l}$, plus any transmission capacity added on that line (for lines eligible for expansion in the set $\mathcal{E}$). The additional transmission capacity, $\bigtriangleup\varphi^{cap}_{l} $, is constrained by a maximum allowed reinforcement, $\overline{\bigtriangleup\varphi^{cap}_{l}}$, for each line $l \in \mathcal{E}$.

\[\begin{aligned} % trasmission constraints @@ -112,19 +112,19 @@ &\mathcal{S}^{-}_{m,l,t} \geq ON^{-}_{m+1,l,t} \times \overline{\mathcal{S}_{m,l}} , &\quad \forall m \in [1:M], \forall l \in \mathcal{L}, \forall t \in \mathcal{T}\\ &\mathcal{S}^{+}_{0,l,t} \leq \varphi^{max}_{l} \times (1- ON^{+}_{1,l,t}), &\quad \forall l \in \mathcal{L}, \forall t \in \mathcal{T}\\ &\mathcal{S}^{-}_{0,l,t} \leq \varphi^{max}_{l} \times (1- ON^{-}_{1,l,t}), &\quad \forall l \in \mathcal{L}, \forall t \in \mathcal{T} -\end{aligned}\]

source

Unit Commitment

GenX.ucommit!Method
ucommit!(EP::Model, inputs::Dict, setup::Dict)

This function creates decision variables and cost expressions associated with thermal plant unit commitment or start-up and shut-down decisions (cycling on/off)

Unit commitment decision variables:

This function defines the following decision variables:

\[\nu_{y,t,z}\]

designates the commitment state of generator cluster $y$ in zone $z$ at time $t$; $\chi_{y,t,z}$ represents number of startup decisions in cluster $y$ in zone $z$ at time $t$; $\zeta_{y,t,z}$ represents number of shutdown decisions in cluster $y$ in zone $z$ at time $t$.

Cost expressions:

The total cost of start-ups across all generators subject to unit commitment ($y \in UC$) and all time periods, t is expressed as:

\[\begin{aligned} +\end{aligned}\]

source

Unit Commitment

GenX.ucommit!Method
ucommit!(EP::Model, inputs::Dict, setup::Dict)

This function creates decision variables and cost expressions associated with thermal plant unit commitment or start-up and shut-down decisions (cycling on/off)

Unit commitment decision variables:

This function defines the following decision variables:

\[\nu_{y,t,z}\]

designates the commitment state of generator cluster $y$ in zone $z$ at time $t$; $\chi_{y,t,z}$ represents number of startup decisions in cluster $y$ in zone $z$ at time $t$; $\zeta_{y,t,z}$ represents number of shutdown decisions in cluster $y$ in zone $z$ at time $t$.

Cost expressions:

The total cost of start-ups across all generators subject to unit commitment ($y \in UC$) and all time periods, t is expressed as:

\[\begin{aligned} C^{start} = \sum_{y \in UC, t \in T} \omega_t \times start\_cost_{y,t} \times \chi_{y,t} -\end{aligned}\]

The sum of start-up costs is added to the objective function.

source

CO2

GenX.co2!Method
co2!(EP::Model, inputs::Dict)

This function creates expressions to account for CO2 emissions as well as captured and sequestrated CO2 from thermal generators. It also has the capability to model the negative CO2 emissions from bioenergy with carbon capture and storage.

***** Expressions *****

For thermal generators which combust fuels (e.g., coal, natural gas, and biomass), the net CO2 emission to the environment is a function of fuel consumption, CO2 emission factor, CO2 capture fraction, and whether the feedstock is biomass. Biomass is a factor in this equation because biomass generators are assumed to generate zero net CO2 emissions, or negative net CO2 emissions in the case that the CO2 they emit is captured and sequestered underground.

If a user wishes to represent a generator that combusts biomass, then in the resource .csv files, the "Biomass" column (boolean, 1 or 0), which represents if a generator $y$ uses biomass or not, should be set to 1. The CO2 emissions from such a generator will be assumed to be zero without CCS and negative with CCS.

The CO2 emissions from generator $y$ at time $t$ are determined by total fuel consumption (MMBTU) multiplied by the CO2 content of the fuel (tCO2/MMBTU), and by (1 - Biomass [0 or 1] - CO2 capture fraction [a fraction, between 0 - 1]). The CO2 capture fraction could be differernt during the steady-state and startup events (generally startup events have a lower CO2 capture fraction), so we use distinct CO2 capture fractions to determine the emissions. In short, the CO2 emissions for a generator depend on the CO2 emission factor from fuel combustion, the CO2 capture fraction, and whether the generator uses biomass.

\[\begin{aligned} +\end{aligned}\]

The sum of start-up costs is added to the objective function.

source

CO2

GenX.co2!Method
co2!(EP::Model, inputs::Dict)

This function creates expressions to account for CO2 emissions as well as captured and sequestrated CO2 from thermal generators. It also has the capability to model the negative CO2 emissions from bioenergy with carbon capture and storage.

***** Expressions *****

For thermal generators which combust fuels (e.g., coal, natural gas, and biomass), the net CO2 emission to the environment is a function of fuel consumption, CO2 emission factor, CO2 capture fraction, and whether the feedstock is biomass. Biomass is a factor in this equation because biomass generators are assumed to generate zero net CO2 emissions, or negative net CO2 emissions in the case that the CO2 they emit is captured and sequestered underground.

If a user wishes to represent a generator that combusts biomass, then in the resource .csv files, the "Biomass" column (boolean, 1 or 0), which represents if a generator $y$ uses biomass or not, should be set to 1. The CO2 emissions from such a generator will be assumed to be zero without CCS and negative with CCS.

The CO2 emissions from generator $y$ at time $t$ are determined by total fuel consumption (MMBTU) multiplied by the CO2 content of the fuel (tCO2/MMBTU), and by (1 - Biomass [0 or 1] - CO2 capture fraction [a fraction, between 0 - 1]). The CO2 capture fraction could be differernt during the steady-state and startup events (generally startup events have a lower CO2 capture fraction), so we use distinct CO2 capture fractions to determine the emissions. In short, the CO2 emissions for a generator depend on the CO2 emission factor from fuel combustion, the CO2 capture fraction, and whether the generator uses biomass.

\[\begin{aligned} eEmissionsByPlant_{g,t} = (1-Biomass_y- CO2\_Capture\_Fraction_y) * vFuel_{y,t} * CO2_{content} + (1-Biomass_y- CO2\_Capture\_Fraction\_Startup_y) * eStartFuel_{y,t} * CO2_{content} \hspace{1cm} \forall y \in G, \forall t \in T, Biomass_y \in {{0,1}} \end{aligned}\]

Where $Biomass_y$ represents a binary variable (1 or 0) that determines if the generator $y$ uses biomass, and $CO2\_Capture\_Fraction_y$ represents a fraction for CO2 capture rate.

In addition to CO2 emissions, for generators with a non-zero CO2 capture rate, we also determine the amount of CO2 being captured and sequestered. The CO2 emissions from generator $y$ at time $t$, denoted by $eEmissionsCaptureByPlant_{g,t}$, are determined by total fuel consumption (MMBTU) multiplied by the $CO_2$ content of the fuel (tCO2/MMBTU), times CO2 capture rate.

\[\begin{aligned} eEmissionsCaptureByPlant_{g,t} = CO2\_Capture\_Fraction_y * vFuel_{y,t} * CO2_{content} + CO2\_Capture\_Fraction\_Startup_y * eStartFuel_{y,t} * CO2_{content} \hspace{1cm} \forall y \in G, \forall t \in T -\end{aligned}\]

source
GenX.write_co2Method
write_co2(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting time-dependent CO2 emissions by zone.

source

Fuel

GenX.fuel!Method
fuel!(EP::Model, inputs::Dict, setup::Dict)

This function creates expressions to account for total fuel consumption (e.g., coal, natural gas, hydrogen, etc). It also has the capability to model heat rates that are a function of load via a piecewise-linear approximation.

***** Expressions ****** Users have two options to model the fuel consumption as a function of power generation: (1). Use a constant heat rate, regardless of the minimum load or maximum load; and (2). Use the PiecewiseFuelUsage-related parameters to model the fuel consumption via a piecewise-linear approximation of the heat rate curves. By using this option, users can represent the fact that most generators have a decreasing heat rate as a function of load.

(1). Constant heat rate. The fuel consumption for power generation $vFuel_{y,t}$ is determined by power generation ($vP_{y,t}$) mutiplied by the corresponding heat rate ($Heat\_Rate_y$). The fuel costs for power generation and start fuel for a plant $y$ at time $t$, denoted by $eCFuelOut_{y,t}$ and $eFuelStart$, are determined by fuel consumption ($vFuel_{y,t}$ and $eStartFuel$) multiplied by the fuel costs ($/MMBTU) (2). Piecewise-linear approximation With this formulation, the heat rate of generators becomes a function of load. In reality this relationship takes a nonlinear form, but we model it through a piecewise-linear approximation:

\[\begin{aligned} +\end{aligned}\]

source
GenX.write_co2Method
write_co2(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting time-dependent CO2 emissions by zone.

source

Fuel

GenX.fuel!Method
fuel!(EP::Model, inputs::Dict, setup::Dict)

This function creates expressions to account for total fuel consumption (e.g., coal, natural gas, hydrogen, etc). It also has the capability to model heat rates that are a function of load via a piecewise-linear approximation.

***** Expressions ****** Users have two options to model the fuel consumption as a function of power generation: (1). Use a constant heat rate, regardless of the minimum load or maximum load; and (2). Use the PiecewiseFuelUsage-related parameters to model the fuel consumption via a piecewise-linear approximation of the heat rate curves. By using this option, users can represent the fact that most generators have a decreasing heat rate as a function of load.

(1). Constant heat rate. The fuel consumption for power generation $vFuel_{y,t}$ is determined by power generation ($vP_{y,t}$) mutiplied by the corresponding heat rate ($Heat\_Rate_y$). The fuel costs for power generation and start fuel for a plant $y$ at time $t$, denoted by $eCFuelOut_{y,t}$ and $eFuelStart$, are determined by fuel consumption ($vFuel_{y,t}$ and $eStartFuel$) multiplied by the fuel costs ($/MMBTU) (2). Piecewise-linear approximation With this formulation, the heat rate of generators becomes a function of load. In reality this relationship takes a nonlinear form, but we model it through a piecewise-linear approximation:

\[\begin{aligned} vFuel_{y,t} >= vP_{y,t} * h_{y,x} + U_{g,t}* f_{y,x} \hspace{1cm} \forall y \in G, \forall t \in T, \forall x \in X \end{aligned}\]

Where $h_{y,x}$ represents the heat rate slope for generator $y$ in segment $x$ [MMBTU/MWh], $f_{y,x}$ represents the heat rate intercept (MMBTU) for a generator $y$ in segment $x$ [MMBTU], and $U_{y,t}$ represents the commitment status of a generator $y$ at time $t$. These parameters are optional inputs to the resource .csv files. When Unit commitment is on, if a user provides slope and intercept, the standard heat rate (i.e., HeatRateMMBTUperMWh) will not be used. When unit commitment is off, the model will always use the standard heat rate. The user should determine the slope and intercept parameters based on the CapSize of the plant. For example, when a plant is operating at the full load (i.e., power output equal to the CapSize), the fuel usage determined by the effective segment divided by Cap_Size should be equal to the heat rate at full-load.

Since fuel consumption and fuel costs are postive, the optimization will force the fuel usage to be equal to the highest fuel usage segment for any given value of vP. When the power output is zero, the commitment variable $U_{g,t}$ will bring the intercept to be zero such that the fuel consumption is zero when thermal units are offline.

In order to run piecewise fuel consumption module, the unit commitment must be turned on (UC = 1 or 2), and users should provide PWFUSlope* and PWFUIntercept* for at least one segment.

To enable resources to use multiple fuels during both startup and normal operational processes, three additional variables were added: fuel $i$ consumption by plant $y$ at time $t$ ($vMulFuel_{y,i,t}$); startup fuel consumption for single-fuel plants ($vStartFuel_{y,t}$); and startup fuel consumption for multi-fuel plants ($vMulStartFuel_{y,i,t}$). By making startup fuel consumption variables, the model can choose the startup fuel to meet the constraints.

For plants using multiple fuels:

During startup, heat input from multiple startup fuels are equal to startup fuel requirements in plant $y$ at time $t$: $StartFuelMMBTUperMW$ times $Capsize$.

\[\begin{aligned} \sum_{i \in \mathcal{I} } vMulStartFuels_{y, i, t}= CapSize_{y} \times StartFuelMMBTUperMW_{y} \times vSTART_{y,t} \end{aligned}\]

During normal operation, the sum of fuel consumptions from multiple fuels dividing by the correspnding heat rates, respectively, is equal to $vPower$ in plant $y$ at time $t$.

\[\begin{aligned} \sum_{i \in \mathcal{I} } \frac{vMulFuels_{y, i, t}} {HeatRate_{i,y} } = vPower_{y,t} -\end{aligned}\]

There are also constraints on how much heat input each fuel can provide, which are specified by $MinCofire$ and $MaxCofire$. ```math \begin{aligned} vMulFuels{y, i, t} >= vPower{y,t} \times MinCofire{i} \end{aligned} \begin{aligned} vMulFuels{y, i, t} <= vPower{y,t} \times MaxCofire{i} \end{aligned}

source
+\end{aligned}\]

There are also constraints on how much heat input each fuel can provide, which are specified by $MinCofire$ and $MaxCofire$. ```math \begin{aligned} vMulFuels{y, i, t} >= vPower{y,t} \times MinCofire{i} \end{aligned} \begin{aligned} vMulFuels{y, i, t} <= vPower{y,t} \times MaxCofire{i} \end{aligned}

source diff --git a/previews/PR655/Model_Reference/generate_model/index.html b/previews/PR655/Model_Reference/generate_model/index.html index 2a24be04b3..63a03ba214 100644 --- a/previews/PR655/Model_Reference/generate_model/index.html +++ b/previews/PR655/Model_Reference/generate_model/index.html @@ -18,4 +18,4 @@ & \sum_{y\in \mathcal{DF}}{(-\Theta_{y,z,t}+\Pi_{y,z,t})} +\sum_{y\in \mathcal{W}}{\Theta_{y,z,t}}+ \notag\\ &+ \sum_{s\in \mathcal{S}}{\Lambda_{s,z,t}} - \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \Phi_{l,t})} -\frac{1}{2} \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \beta_{l,t}(\cdot))} = D_{z,t} \forall z\in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

Arguments

Returns

source +\end{aligned}\]

Arguments

Returns

source diff --git a/previews/PR655/Model_Reference/load_inputs/index.html b/previews/PR655/Model_Reference/load_inputs/index.html index 8aaa9247b1..3a81f9ac66 100644 --- a/previews/PR655/Model_Reference/load_inputs/index.html +++ b/previews/PR655/Model_Reference/load_inputs/index.html @@ -1,8 +1,8 @@ -Inputs Functions · GenX

Reading Input Files

GenX.get_systemfiles_pathMethod
get_systemfiles_path(setup::Dict, TDR_directory::AbstractString, path::AbstractString)

Determine the directory based on the setup parameters.

This function checks if the TimeDomainReduction setup parameter is equal to 1 and if time domain reduced files exist in the data directory. If the condition is met, it returns the path to the TDR_results data directory. Otherwise, it returns the system directory specified in the setup.

Parameters:

  • setup: Dict{String, Any} - The GenX settings parameters containing TimeDomainReduction and SystemFolder information.
  • TDR_directory: String - The data directory where files are located.
  • path: String - Path to the case folder.

Returns:

  • String: The directory path based on the setup parameters.
source
GenX.load_inputsMethod
load_inputs(setup::Dict,path::AbstractString)

Loads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function

inputs: setup - dict object containing setup parameters path - string path to working directory

returns: Dict (dictionary) object containing all data inputs

source

Fuels Data

GenX.load_fuels_data!Method
load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to fuel costs and CO$_2$ content of fuels

source

Generators Input Data

GenX._get_policyfile_infoMethod
_get_policyfile_info()

Internal function to get policy file information.

Returns

policyfile_info (NamedTuple): A tuple containing policy file information.
source
GenX._get_resource_infoMethod
_get_resource_info()

Internal function to get resource information (filename and GenX type) for each type of resource available in GenX.

resource_info (NamedTuple): A tuple containing resource information.
source
GenX._get_summary_mapMethod
_get_summary_map()

Internal function to get a map of GenX resource type their corresponding names in the summary table.

source
GenX.add_attributes_to_resource!Method
add_attributes_to_resource!(resource::AbstractResource, new_symbols::Vector{Symbol}, new_values::T) where T <: DataFrameRow

Adds a set of new attributes (names and corresponding values) to a resource. The resource is modified in-place.

Arguments

  • resource::AbstractResource: The resource to add attributes to.
  • new_symbols::Vector{Symbol}: Vector of symbols containing the names of the new attributes.
  • new_values::DataFrameRow: DataFrameRow containing the values of the new attributes.
source
GenX.add_df_to_resources!Method
add_df_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)

Adds the data contained in a DataFrame to a vector of resources. Each row in the DataFrame corresponds to a resource. If the name of the resource in the DataFrame matches a name of a resource in the model, all the columns of that DataFrameRow are added as new attributes to the corresponding resource.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • module_in::DataFrame: The dataframe to add.
source
GenX.add_id_to_resource_df!Method
add_id_to_resource_df!(df::DataFrame, indices::AbstractVector)

Adds a new column 'id' to the DataFrame with the provided resource indices. The dataframe is modified in-place.

Arguments

  • df::DataFrame: The input DataFrame to which the indices are to be added.
  • indices::AbstractVector: The array of indices to be added as a new column.
source
GenX.add_module_to_resources!Method
add_module_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)

Reads module dataframe and adds columns as new attributes to the resources in the model if the resource name in the module file matches a resource name in the model. The module file is assumed to have a column named "resource" containing the resource names.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • module_in::DataFrame: The dataframe with the columns to add to the resources.
source
GenX.add_modules_to_resources!Method
add_modules_to_resources!(resources::Vector{<:AbstractResource}, setup::Dict, resources_path::AbstractString)

Reads module dataframes, loops over files and adds columns as new attributes to the resources in the model.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • setup (Dict): A dictionary containing GenX settings.
  • resources_path::AbstractString: The path to the resources folder.
source
GenX.add_policies_to_resources!Method
add_policies_to_resources!(resources::Vector{<:AbstractResource}, resources_path::AbstractString)

Reads policy files and adds policies-related attributes to resources in the model.

Arguments

  • resources::Vector{<:AbstractResource}: Vector of resources in the model.
  • resources_path::AbstractString: The path to the resources folder.
source
GenX.add_policy_to_resources!Method
add_policy_to_resources!(resources::Vector{<:AbstractResource}, path::AbstractString, filename::AbstractString)

Loads a single policy file and adds the columns as new attributes to resources in the model if the resource name in the policy file matches a resource name in the model. The policy file is assumed to have a column named "resource" containing the resource names.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • path::AbstractString: The path to the policy file.
  • filename::AbstractString: The name of the policy file.
source
GenX.add_resources_to_input_data!Method
add_resources_to_input_data!(inputs::Dict, setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource})

Adds resources to the inputs Dict with the key "RESOURCES" together with sevaral sets of resource indices that are used inside GenX to construct the optimization problem. The inputs Dict is modified in-place.

Arguments

  • inputs (Dict): Dictionary to store the GenX input data.
  • setup (Dict): Dictionary containing GenX settings.
  • case_path (AbstractString): Path to the case.
  • gen (Vector{<:AbstractResource}): Array of GenX resources.
source
GenX.check_resourceMethod
check_resource(resources::Vector{T})::Vector{String} where T <: AbstractResource

Validate the consistency of a vector of GenX resources Reports any errors/warnings as a vector of messages.

source
GenX.compute_resource_indicesMethod
compute_resource_indices(resources_in::DataFrame, offset::Int64)

Computes the indices for the resources loaded from a single dataframe by shifting the indices by an offset value.

Arguments

  • resources_in::DataFrame: The input DataFrame containing the resources.
  • offset::Int64: The offset value to be added to the indices.

Returns

  • UnitRange{Int64}: An array of indices.
source
GenX.create_resource_arrayFunction
create_resource_array(resource_folder::AbstractString, resources_info::NamedTuple, scale_factor::Float64=1.0)

Construct the array of resources from multiple files of different types located in the specified resource_folder. The resources_info NamedTuple contains the filename and GenX type for each type of resource available in GenX.

Arguments

  • resource_folder::AbstractString: The path to the folder containing the resource files.
  • resources_info::NamedTuple: A NamedTuple that maps a resource type to its filename and GenX type.
  • scale_factor::Float64: A scaling factor to adjust the attributes of the resources (default: 1.0).

Returns

  • Vector{<:AbstractResource}: An array of GenX resources.

Raises

  • Error: If no resources data is found. Check the data path or the configuration file "genx_settings.yml" inside Settings.
source
GenX.create_resource_arrayMethod
create_resource_array(setup::Dict, resources_path::AbstractString)

Function that loads and scales resources data from folder specified in resources_path and returns an array of GenX resources.

Arguments

  • setup (Dict): Dictionary containing GenX settings.
  • resources_path (AbstractString): The path to the resources folder.

Returns

  • resources (Vector{<:AbstractResource}): An array of scaled resources.
source
GenX.create_resources_sametypeMethod
create_resources_sametype(resource_in::DataFrame, ResourceType)

This function takes a DataFrame resource_in and a GenX ResourceType type, and converts the DataFrame to an array of AbstractResource of the specified type.

Arguments

  • resource_in::DataFrame: The input DataFrame containing the resources belonging to a specific type.
  • ResourceType: The GenX type of resources to be converted to.

Returns

  • resources::Vector{ResourceType}: An array of resources of the specified type.
source
GenX.dataframerow_to_dictMethod
dataframerow_to_dict(dfr::DataFrameRow)

Converts a DataFrameRow to a Dict.

Arguments

  • dfr::DataFrameRow: The DataFrameRow to be converted.

Returns

  • Dict: Dictionary containing the DataFrameRow data.
source
GenX.load_multi_fuels_data!Method
load_multi_fuels_data!(inputs::Dict, gen::Vector{<:AbstractResource}, setup::Dict, path::AbstractString)

Function for reading input parameters related to multi fuels

source
GenX.load_resource_dfMethod
load_resource_df(path::AbstractString, scale_factor::Float64, resource_type::Type)

Function to load and scale the dataframe of a given resource.

Arguments

  • path::AbstractString: Path to the resource dataframe.
  • scale_factor::Float64: Scaling factor for the resource data.
  • resource_type::Type: GenX type of the resource.

Returns

  • resource_in::DataFrame: The loaded and scaled resource data.
source
GenX.load_resources_data!Method
load_resources_data!(inputs::Dict, setup::Dict, case_path::AbstractString, resources_path::AbstractString)

This function loads resources data from the resources_path folder and create the GenX data structures and add them to the inputs Dict.

Arguments

  • inputs (Dict): A dictionary to store the input data.
  • setup (Dict): A dictionary containing GenX settings.
  • case_path (AbstractString): The path to the case folder.
  • resources_path (AbstractString): The path to the case resources folder.

Raises: DeprecationWarning: If the Generators_data.csv file is found, a deprecation warning is issued, together with an error message.

source
GenX.process_piecewisefuelusage!Method
process_piecewisefuelusage!(setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource}, inputs::Dict)

Reads piecewise fuel usage data from the vector of generators, create a PWFU_data that contain processed intercept and slope (i.e., heat rate) and add them to the inputs dictionary.

Arguments

  • setup::Dict: The dictionary containing the setup parameters
  • case_path::AbstractString: The path to the case folder
  • gen::Vector{<:AbstractResource}: The vector of generators in the model
  • inputs::Dict: The dictionary containing the input data
source
GenX.scale_columns!Method
scale_columns!(df::DataFrame, columns_to_scale::Vector{Symbol}, scale_factor::Float64)

Scales in-place the columns in columns_to_scale of a dataframe df by a scale_factor.

Arguments

  • df (DataFrame): A dataframe containing data to scale.
  • columns_to_scale (Vector{Symbol}): A vector of column names to scale.
  • scale_factor (Float64): A scaling factor for energy and currency units.
source
GenX.scale_resources_data!Method
scale_resources_data!(resource_in::DataFrame, scale_factor::Float64)

Scales resources attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.

Arguments

  • resource_in (DataFrame): A dataframe containing data for a specific resource.
  • scale_factor (Float64): A scaling factor for energy and currency units.
source
GenX.scale_vre_stor_data!Method
scale_vre_stor_data!(vre_stor_in::DataFrame, scale_factor::Float64)

Scales vre_stor attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.

Arguments

  • vre_stor_in (DataFrame): A dataframe containing data for co-located VREs and storage.
  • scale_factor (Float64): A scaling factor for energy and currency units.
source
GenX.split_storage_resources!Method
split_storage_resources!(inputs::Dict, gen::Vector{<:AbstractResource})

For co-located VRE-storage resources, this function returns the storage type (1. long-duration or short-duration storage, 2. symmetric or asymmetric storage) for charging and discharging capacities

source
GenX.summaryMethod
summary(rs::Vector{<:AbstractResource})

Prints a summary of the resources loaded into the model.

Arguments

  • rs (Vector{<:AbstractResource}): An array of GenX resources.
source
GenX.update_retrofit_idMethod
update_retrofit_id(r::AbstractResource)

Updates the retrofitid of a resource that can be retrofit or is a retrofit option by appending the region to the retrofitid.

Arguments

  • r::AbstractResource: The resource to update.
source
GenX.validate_policy_dataframe!Method
validate_policy_dataframe!(filename::AbstractString, policy_in::DataFrame)

Validate the policy dataframe by checking if it has any attributes and if the column names are valid. The dataframe is modified in-place.

Arguments

  • filename::AbstractString: The name of the policy file.
  • policy_in::DataFrame: The policy dataframe.
source
GenX.validate_policy_filesMethod
validate_policy_files(resource_policies_path::AbstractString, setup::Dict)

Validate the policy files by checking if they exist in the specified folder and if the setup flags are consistent with the files found.

Arguments

  • resource_policies_path::AbstractString: The path to the policy files.
  • setup::Dict: Dictionary containing GenX settings.

Returns

  • warning messages if the polcies are set to 1 in settings but the files are not found in the resourcepoliciespath.

!isfile(joinpath(resourcepoliciespath, filename))

source

Variability of Generators' Outputs

GenX.load_generators_variability!Method
load_generators_variability!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to hourly maximum capacity factors for generators, storage, and flexible demand resources

source

Demand Data

GenX.load_demand_data!Method
load_demand_data!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to electricity demand (load)

source
GenX.prevent_doubled_timedomainreductionMethod
prevent_doubled_timedomainreduction(path::AbstractString)

This function prevents TimeDomainReduction from running on a case which already has more than one Representative Period or has more than one Sub_Weight specified.

source

Transmission Network

GenX.load_network_data!Method
load_network_data!(setup::Dict, path::AbstractString, inputs_nw::Dict)

Function for reading input parameters related to the electricity transmission network

source
GenX.load_network_map_from_listMethod
load_network_map_from_list(network_var::DataFrame, Z, L, list_columns)

Loads the network map from a list-style interface

..., Network_Lines, Start_Zone, End_Zone, ...
+Inputs Functions · GenX

Reading Input Files

GenX.get_systemfiles_pathMethod
get_systemfiles_path(setup::Dict, TDR_directory::AbstractString, path::AbstractString)

Determine the directory based on the setup parameters.

This function checks if the TimeDomainReduction setup parameter is equal to 1 and if time domain reduced files exist in the data directory. If the condition is met, it returns the path to the TDR_results data directory. Otherwise, it returns the system directory specified in the setup.

Parameters:

  • setup: Dict{String, Any} - The GenX settings parameters containing TimeDomainReduction and SystemFolder information.
  • TDR_directory: String - The data directory where files are located.
  • path: String - Path to the case folder.

Returns:

  • String: The directory path based on the setup parameters.
source
GenX.load_inputsMethod
load_inputs(setup::Dict,path::AbstractString)

Loads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function

inputs: setup - dict object containing setup parameters path - string path to working directory

returns: Dict (dictionary) object containing all data inputs

source

Fuels Data

GenX.load_fuels_data!Method
load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to fuel costs and CO$_2$ content of fuels

source

Generators Input Data

GenX._get_policyfile_infoMethod
_get_policyfile_info()

Internal function to get policy file information.

Returns

policyfile_info (NamedTuple): A tuple containing policy file information.
source
GenX._get_resource_infoMethod
_get_resource_info()

Internal function to get resource information (filename and GenX type) for each type of resource available in GenX.

resource_info (NamedTuple): A tuple containing resource information.
source
GenX._get_summary_mapMethod
_get_summary_map()

Internal function to get a map of GenX resource type their corresponding names in the summary table.

source
GenX.add_attributes_to_resource!Method
add_attributes_to_resource!(resource::AbstractResource, new_symbols::Vector{Symbol}, new_values::T) where T <: DataFrameRow

Adds a set of new attributes (names and corresponding values) to a resource. The resource is modified in-place.

Arguments

  • resource::AbstractResource: The resource to add attributes to.
  • new_symbols::Vector{Symbol}: Vector of symbols containing the names of the new attributes.
  • new_values::DataFrameRow: DataFrameRow containing the values of the new attributes.
source
GenX.add_df_to_resources!Method
add_df_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)

Adds the data contained in a DataFrame to a vector of resources. Each row in the DataFrame corresponds to a resource. If the name of the resource in the DataFrame matches a name of a resource in the model, all the columns of that DataFrameRow are added as new attributes to the corresponding resource.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • module_in::DataFrame: The dataframe to add.
source
GenX.add_id_to_resource_df!Method
add_id_to_resource_df!(df::DataFrame, indices::AbstractVector)

Adds a new column 'id' to the DataFrame with the provided resource indices. The dataframe is modified in-place.

Arguments

  • df::DataFrame: The input DataFrame to which the indices are to be added.
  • indices::AbstractVector: The array of indices to be added as a new column.
source
GenX.add_module_to_resources!Method
add_module_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)

Reads module dataframe and adds columns as new attributes to the resources in the model if the resource name in the module file matches a resource name in the model. The module file is assumed to have a column named "resource" containing the resource names.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • module_in::DataFrame: The dataframe with the columns to add to the resources.
source
GenX.add_modules_to_resources!Method
add_modules_to_resources!(resources::Vector{<:AbstractResource}, setup::Dict, resources_path::AbstractString)

Reads module dataframes, loops over files and adds columns as new attributes to the resources in the model.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • setup (Dict): A dictionary containing GenX settings.
  • resources_path::AbstractString: The path to the resources folder.
source
GenX.add_policies_to_resources!Method
add_policies_to_resources!(resources::Vector{<:AbstractResource}, resources_path::AbstractString)

Reads policy files and adds policies-related attributes to resources in the model.

Arguments

  • resources::Vector{<:AbstractResource}: Vector of resources in the model.
  • resources_path::AbstractString: The path to the resources folder.
source
GenX.add_policy_to_resources!Method
add_policy_to_resources!(resources::Vector{<:AbstractResource}, path::AbstractString, filename::AbstractString)

Loads a single policy file and adds the columns as new attributes to resources in the model if the resource name in the policy file matches a resource name in the model. The policy file is assumed to have a column named "resource" containing the resource names.

Arguments

  • resources::Vector{<:AbstractResource}: A vector of resources.
  • path::AbstractString: The path to the policy file.
  • filename::AbstractString: The name of the policy file.
source
GenX.add_resources_to_input_data!Method
add_resources_to_input_data!(inputs::Dict, setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource})

Adds resources to the inputs Dict with the key "RESOURCES" together with sevaral sets of resource indices that are used inside GenX to construct the optimization problem. The inputs Dict is modified in-place.

Arguments

  • inputs (Dict): Dictionary to store the GenX input data.
  • setup (Dict): Dictionary containing GenX settings.
  • case_path (AbstractString): Path to the case.
  • gen (Vector{<:AbstractResource}): Array of GenX resources.
source
GenX.check_resourceMethod
check_resource(resources::Vector{T})::Vector{String} where T <: AbstractResource

Validate the consistency of a vector of GenX resources Reports any errors/warnings as a vector of messages.

source
GenX.compute_resource_indicesMethod
compute_resource_indices(resources_in::DataFrame, offset::Int64)

Computes the indices for the resources loaded from a single dataframe by shifting the indices by an offset value.

Arguments

  • resources_in::DataFrame: The input DataFrame containing the resources.
  • offset::Int64: The offset value to be added to the indices.

Returns

  • UnitRange{Int64}: An array of indices.
source
GenX.create_resource_arrayFunction
create_resource_array(resource_folder::AbstractString, resources_info::NamedTuple, scale_factor::Float64=1.0)

Construct the array of resources from multiple files of different types located in the specified resource_folder. The resources_info NamedTuple contains the filename and GenX type for each type of resource available in GenX.

Arguments

  • resource_folder::AbstractString: The path to the folder containing the resource files.
  • resources_info::NamedTuple: A NamedTuple that maps a resource type to its filename and GenX type.
  • scale_factor::Float64: A scaling factor to adjust the attributes of the resources (default: 1.0).

Returns

  • Vector{<:AbstractResource}: An array of GenX resources.

Raises

  • Error: If no resources data is found. Check the data path or the configuration file "genx_settings.yml" inside Settings.
source
GenX.create_resource_arrayMethod
create_resource_array(setup::Dict, resources_path::AbstractString)

Function that loads and scales resources data from folder specified in resources_path and returns an array of GenX resources.

Arguments

  • setup (Dict): Dictionary containing GenX settings.
  • resources_path (AbstractString): The path to the resources folder.

Returns

  • resources (Vector{<:AbstractResource}): An array of scaled resources.
source
GenX.create_resources_sametypeMethod
create_resources_sametype(resource_in::DataFrame, ResourceType)

This function takes a DataFrame resource_in and a GenX ResourceType type, and converts the DataFrame to an array of AbstractResource of the specified type.

Arguments

  • resource_in::DataFrame: The input DataFrame containing the resources belonging to a specific type.
  • ResourceType: The GenX type of resources to be converted to.

Returns

  • resources::Vector{ResourceType}: An array of resources of the specified type.
source
GenX.dataframerow_to_dictMethod
dataframerow_to_dict(dfr::DataFrameRow)

Converts a DataFrameRow to a Dict.

Arguments

  • dfr::DataFrameRow: The DataFrameRow to be converted.

Returns

  • Dict: Dictionary containing the DataFrameRow data.
source
GenX.load_multi_fuels_data!Method
load_multi_fuels_data!(inputs::Dict, gen::Vector{<:AbstractResource}, setup::Dict, path::AbstractString)

Function for reading input parameters related to multi fuels

source
GenX.load_resource_dfMethod
load_resource_df(path::AbstractString, scale_factor::Float64, resource_type::Type)

Function to load and scale the dataframe of a given resource.

Arguments

  • path::AbstractString: Path to the resource dataframe.
  • scale_factor::Float64: Scaling factor for the resource data.
  • resource_type::Type: GenX type of the resource.

Returns

  • resource_in::DataFrame: The loaded and scaled resource data.
source
GenX.load_resources_data!Method
load_resources_data!(inputs::Dict, setup::Dict, case_path::AbstractString, resources_path::AbstractString)

This function loads resources data from the resources_path folder and create the GenX data structures and add them to the inputs Dict.

Arguments

  • inputs (Dict): A dictionary to store the input data.
  • setup (Dict): A dictionary containing GenX settings.
  • case_path (AbstractString): The path to the case folder.
  • resources_path (AbstractString): The path to the case resources folder.

Raises: DeprecationWarning: If the Generators_data.csv file is found, a deprecation warning is issued, together with an error message.

source
GenX.process_piecewisefuelusage!Method
process_piecewisefuelusage!(setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource}, inputs::Dict)

Reads piecewise fuel usage data from the vector of generators, create a PWFU_data that contain processed intercept and slope (i.e., heat rate) and add them to the inputs dictionary.

Arguments

  • setup::Dict: The dictionary containing the setup parameters
  • case_path::AbstractString: The path to the case folder
  • gen::Vector{<:AbstractResource}: The vector of generators in the model
  • inputs::Dict: The dictionary containing the input data
source
GenX.scale_columns!Method
scale_columns!(df::DataFrame, columns_to_scale::Vector{Symbol}, scale_factor::Float64)

Scales in-place the columns in columns_to_scale of a dataframe df by a scale_factor.

Arguments

  • df (DataFrame): A dataframe containing data to scale.
  • columns_to_scale (Vector{Symbol}): A vector of column names to scale.
  • scale_factor (Float64): A scaling factor for energy and currency units.
source
GenX.scale_resources_data!Method
scale_resources_data!(resource_in::DataFrame, scale_factor::Float64)

Scales resources attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.

Arguments

  • resource_in (DataFrame): A dataframe containing data for a specific resource.
  • scale_factor (Float64): A scaling factor for energy and currency units.
source
GenX.scale_vre_stor_data!Method
scale_vre_stor_data!(vre_stor_in::DataFrame, scale_factor::Float64)

Scales vre_stor attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.

Arguments

  • vre_stor_in (DataFrame): A dataframe containing data for co-located VREs and storage.
  • scale_factor (Float64): A scaling factor for energy and currency units.
source
GenX.split_storage_resources!Method
split_storage_resources!(inputs::Dict, gen::Vector{<:AbstractResource})

For co-located VRE-storage resources, this function returns the storage type (1. long-duration or short-duration storage, 2. symmetric or asymmetric storage) for charging and discharging capacities

source
GenX.summaryMethod
summary(rs::Vector{<:AbstractResource})

Prints a summary of the resources loaded into the model.

Arguments

  • rs (Vector{<:AbstractResource}): An array of GenX resources.
source
GenX.update_retrofit_idMethod
update_retrofit_id(r::AbstractResource)

Updates the retrofitid of a resource that can be retrofit or is a retrofit option by appending the region to the retrofitid.

Arguments

  • r::AbstractResource: The resource to update.
source
GenX.validate_policy_dataframe!Method
validate_policy_dataframe!(filename::AbstractString, policy_in::DataFrame)

Validate the policy dataframe by checking if it has any attributes and if the column names are valid. The dataframe is modified in-place.

Arguments

  • filename::AbstractString: The name of the policy file.
  • policy_in::DataFrame: The policy dataframe.
source
GenX.validate_policy_filesMethod
validate_policy_files(resource_policies_path::AbstractString, setup::Dict)

Validate the policy files by checking if they exist in the specified folder and if the setup flags are consistent with the files found.

Arguments

  • resource_policies_path::AbstractString: The path to the policy files.
  • setup::Dict: Dictionary containing GenX settings.

Returns

  • warning messages if the polcies are set to 1 in settings but the files are not found in the resourcepoliciespath.

!isfile(joinpath(resourcepoliciespath, filename))

source

Variability of Generators' Outputs

GenX.load_generators_variability!Method
load_generators_variability!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to hourly maximum capacity factors for generators, storage, and flexible demand resources

source

Demand Data

GenX.load_demand_data!Method
load_demand_data!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to electricity demand (load)

source
GenX.prevent_doubled_timedomainreductionMethod
prevent_doubled_timedomainreduction(path::AbstractString)

This function prevents TimeDomainReduction from running on a case which already has more than one Representative Period or has more than one Sub_Weight specified.

source

Transmission Network

GenX.load_network_data!Method
load_network_data!(setup::Dict, path::AbstractString, inputs_nw::Dict)

Function for reading input parameters related to the electricity transmission network

source
GenX.load_network_map_from_listMethod
load_network_map_from_list(network_var::DataFrame, Z, L, list_columns)

Loads the network map from a list-style interface

..., Network_Lines, Start_Zone, End_Zone, ...
                  1,           1,       2,
-                 2,           1,       3,
source
GenX.load_network_map_from_matrixMethod
load_network_map_from_matrix(network_var::DataFrame, Z, L)

Loads the network map from a matrix-style interface

..., Network_Lines, z1, z2, z3, ...
+                 2,           1,       3,
source
GenX.load_network_map_from_matrixMethod
load_network_map_from_matrix(network_var::DataFrame, Z, L)

Loads the network map from a matrix-style interface

..., Network_Lines, z1, z2, z3, ...
                  1,  1, -1,  0,
-                 2,  1,  0, -1,

This is equivalent to the list-style interface where the zone zN with entry +1 is the starting zone of the line and the zone with entry -1 is the ending zone of the line.

source

Minimum Capacity Requirements

GenX.load_minimum_capacity_requirement!Method
load_minimum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)

Read input parameters related to mimimum capacity requirement constraints (e.g. technology specific deployment mandates)

source

Capacity Reserve Margin

GenX.load_cap_reserve_margin!Method
load_cap_reserve_margin!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to planning reserve margin constraints

source
GenX.load_cap_reserve_margin_trans!Method
load_cap_reserve_margin_trans!(setup::Dict, inputs::Dict, network_var::DataFrame)

Read input parameters related to participation of transmission imports/exports in capacity reserve margin constraint.

source

CO$_2$ Emissions Cap

GenX.load_co2_cap!Method
load_co2_cap!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to CO$_2$ emissions cap constraints

source

Energy Share Requirement

GenX.load_energy_share_requirement!Method
load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)

source

Mapping Representative Time Periods

GenX.load_period_map!Method
load_period_map!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to mapping of representative time periods to full chronological time series

source

Variability of the Solar PV and Wind Components' Outputs (for Co-located Storage Resources)

GenX.load_vre_stor_variability!Method
load_vre_stor_variability!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to hourly maximum capacity factors for the solar PV (DC capacity factors) component and wind (AC capacity factors) component of co-located generators

source

Functions for developers

Standardized loading of dataframes from CSV files

GenX.extract_matrix_from_dataframeMethod
extract_matrix_from_dataframe(df::DataFrame, columnprefix::AbstractString)

Finds all columns in the dataframe which are of the form columnprefix_[Integer], and extracts them in order into a matrix. The function also checks that there's at least one column with this prefix, and that all columns numbered from 1...N exist.

This is now acceptable:

ESR_1, other_thing, ESR_3, ESR_2,
+                 2,  1,  0, -1,

This is equivalent to the list-style interface where the zone zN with entry +1 is the starting zone of the line and the zone with entry -1 is the ending zone of the line.

source

Minimum Capacity Requirements

GenX.load_minimum_capacity_requirement!Method
load_minimum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)

Read input parameters related to mimimum capacity requirement constraints (e.g. technology specific deployment mandates)

source

Capacity Reserve Margin

GenX.load_cap_reserve_margin!Method
load_cap_reserve_margin!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to planning reserve margin constraints

source
GenX.load_cap_reserve_margin_trans!Method
load_cap_reserve_margin_trans!(setup::Dict, inputs::Dict, network_var::DataFrame)

Read input parameters related to participation of transmission imports/exports in capacity reserve margin constraint.

source

CO$_2$ Emissions Cap

GenX.load_co2_cap!Method
load_co2_cap!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to CO$_2$ emissions cap constraints

source

Energy Share Requirement

GenX.load_energy_share_requirement!Method
load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)

source

Mapping Representative Time Periods

GenX.load_period_map!Method
load_period_map!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to mapping of representative time periods to full chronological time series

source

Variability of the Solar PV and Wind Components' Outputs (for Co-located Storage Resources)

GenX.load_vre_stor_variability!Method
load_vre_stor_variability!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to hourly maximum capacity factors for the solar PV (DC capacity factors) component and wind (AC capacity factors) component of co-located generators

source

Functions for developers

Standardized loading of dataframes from CSV files

GenX.extract_matrix_from_dataframeMethod
extract_matrix_from_dataframe(df::DataFrame, columnprefix::AbstractString)

Finds all columns in the dataframe which are of the form columnprefix_[Integer], and extracts them in order into a matrix. The function also checks that there's at least one column with this prefix, and that all columns numbered from 1...N exist.

This is now acceptable:

ESR_1, other_thing, ESR_3, ESR_2,
   0.1,           1,   0.3,   0.2,
-  0.4,           2,   0.6,   0.5,
source
GenX.file_existsMethod
file_exists(dir::AbstractString, basenames::Vector{String})::Bool

Checks that a file exists in a directory under (at least) one of a list of 'aliases'.

source
GenX.load_dataframeMethod
load_dataframe(dir::AbstractString, base::AbstractString)

Attempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.

source
GenX.load_dataframeMethod
load_dataframe(path::AbstractString)

Attempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.

source
GenX.validate_df_colsMethod
validate_df_cols(df::DataFrame, df_name::AbstractString, required_cols::Vector{AbstractString})

Check that the dataframe has all the required columns.

Arguments

  • df::DataFrame: the dataframe to check
  • df_name::AbstractString: the name of the dataframe, for error messages
  • required_cols::Vector{AbstractString}: the names of the required columns
source
+ 0.4, 2, 0.6, 0.5,
source
GenX.file_existsMethod
file_exists(dir::AbstractString, basenames::Vector{String})::Bool

Checks that a file exists in a directory under (at least) one of a list of 'aliases'.

source
GenX.load_dataframeMethod
load_dataframe(dir::AbstractString, base::AbstractString)

Attempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.

source
GenX.load_dataframeMethod
load_dataframe(path::AbstractString)

Attempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.

source
GenX.validate_df_colsMethod
validate_df_cols(df::DataFrame, df_name::AbstractString, required_cols::Vector{AbstractString})

Check that the dataframe has all the required columns.

Arguments

  • df::DataFrame: the dataframe to check
  • df_name::AbstractString: the name of the dataframe, for error messages
  • required_cols::Vector{AbstractString}: the names of the required columns
source
diff --git a/previews/PR655/Model_Reference/maintenance_overview/index.html b/previews/PR655/Model_Reference/maintenance_overview/index.html index 9ef6733cf2..e485c367f5 100644 --- a/previews/PR655/Model_Reference/maintenance_overview/index.html +++ b/previews/PR655/Model_Reference/maintenance_overview/index.html @@ -1,2 +1,2 @@ -Maintenance · GenX

Optimized Scheduled Maintenance

Added in v0.4

In the real world, some types of resources (notably, fission) require regular scheduled maintenance, which often takes several weeks. During this time, the plant produces no power. This module allows GenX to find the best time of year for plants to undergo maintenance.

Scheduled maintenance is implemented only for thermal plants with unit commitment (THERM=1).

Description of the maintenance model

A plant requires a single contiguous period of $h \ge 1$ hours of maintenance, every $y \ge 1$ years. For each plant, the best time to start the maintenance period is determined by the optimizer.

During maintenance, the plant cannot be "commited", and therefore

  • uses no fuel,
  • produces no power,
  • and does not contribute to reserves.

Additionally,

  • the plant does not contribute to any Capacity Reserve Margin.

Treatment of plants that require maintenance only every few years

GenX models a long-term equilibrium, and each problem generally represents a single full year. If a plant requires maintenance every $y$ years, we take the simplification that at least $1/y$ of the plants must undergo maintenance in the modeled year.

See also "Interaction with integer unit commitment" below.

Reduction of number of possible start dates

This module creates constraints which work across long periods, and consequently can be very expensive to solve. In order to reduce the expense, the set of possible maintenance start dates can be limited. Rather than have maintenance potentially start every hour, one can have possible start dates which are once per day, once per week, etc. (In reality, maintenance is likely scheduled months in advance, so optimizing down to the hour may not be realistic anyway.)

How to use

There are four columns which need to be added to the plant data, i.e. in Generators_data.csv:

  1. MAINT should be 1 for plants that require maintenance and 0 otherwise.
  2. Maintenance_Duration is the number of hours the maintenance period lasts.
  3. Maintenance_Cycle_Length_Years. If 1, maintenance every year, if 3 maintenance every 3 years, etc.
  4. Maintenance_Begin_Cadence. Spacing between hours in which maintenance can start.

The last three fields must be integers which are greater than 0. They are ignored for any plants which do not require maintenance.

Maintenance_Duration must be less than the total number of hours in the year.

If Maintenance_Begin_Cadence is 1 then the maintenance can begin in any hour. If it is 168 then it can begin in hours 1, 169, 337, etc.

Restrictions on use

The maintenance module has these restrictions:

  • More than a single maintenance period per year (i.e. every three months) is not possible in the current formulation.
  • Only full-year cases can be run; there must be only one "representative period".

It would not make sense to model a month-long maintenance period when the year is modeled as a series of representative weeks, for example.

Interaction with integer unit commitment

If integer unit commitment is on (UCommit=1) this module may not produce correct results; there may be more maintenance than the user wants. This is because the formulation specifies that the number of plants that go down for maintenance in the simulated year must be at least (the number of plants in the zone)/(the maintenance cycle length in years). As a reminder, the number of plants is eTotalCap / Cap_Size.

If there were three 500 MW plants (total 1500 MW) in a zone, and they require maintenance every three years (Maintenance_Cycle_Length_Years=3), the formulation will work properly: one of the three plants will go under maintenance.

But if there was only one 500 MW plant, and it requires maintenance every 3 years, the constraint will still make it do maintenance every year, because ceil(1/3) is 1. The whole 500 MW plant will do maintenance. This is the unexpected behavior.

However, if integer unit commitment was relaxed to "linearized" unit commitment (UCommit=2), the model will have only 500 MW / 3 = 166.6 MW worth of this plant do maintenance.

Hint: pre-scheduling maintenance

If you want to pre-schedule when maintenance occurs, you might not need this module. Instead, you could set the maximum power output of the plant to zero for a certain period, or make its fuel extremely expensive during that time. However, the plant would still be able to contribute to the Capacity Reserve Margin.

Outputs produced

If at least one plant has MAINT=1, a file maint_down.csv will be written listing how many plants are down for maintenance in each timestep.

Notes on mathematical formulation

The formulation of the maintenance state is very similar to the formulation of unit commitment.

There is a variable called something like vMSHUT which is analogous to vSTART and controls the start of the maintenance period. There is another variable called something like vMDOWN analogous to vCOMMIT which controls the maintenance status in any hour.

A constraint ensures that the value of vMDOWN in any hour is always more than the number of vMSHUTs in the previous Maintenance_Duration hours.

Another constraint ensures that the number of plants committed (vCOMMIT) at any one time plus the number of plants under maintenance (vMDOWN) is less than the total number of plants.

Developer note: adding maintenance to a resource

The maintenance formulation is applied on a per-resource basis, by calling the function GenX.maintenance_formulation!.

See GenX.maintenance_formulation_thermal_commit! for an example of how to apply it to a new resource.

  • The resource must have a vCOMMIT-like variable which is proportional to maximum the power output, etc at any given timestep.
  • The resource must have a eTotalCap-like quantity and a Cap_Size-like parameter; only the ratio of the two is used.
+Maintenance · GenX

Optimized Scheduled Maintenance

Added in v0.4

In the real world, some types of resources (notably, fission) require regular scheduled maintenance, which often takes several weeks. During this time, the plant produces no power. This module allows GenX to find the best time of year for plants to undergo maintenance.

Scheduled maintenance is implemented only for thermal plants with unit commitment (THERM=1).

Description of the maintenance model

A plant requires a single contiguous period of $h \ge 1$ hours of maintenance, every $y \ge 1$ years. For each plant, the best time to start the maintenance period is determined by the optimizer.

During maintenance, the plant cannot be "commited", and therefore

  • uses no fuel,
  • produces no power,
  • and does not contribute to reserves.

Additionally,

  • the plant does not contribute to any Capacity Reserve Margin.

Treatment of plants that require maintenance only every few years

GenX models a long-term equilibrium, and each problem generally represents a single full year. If a plant requires maintenance every $y$ years, we take the simplification that at least $1/y$ of the plants must undergo maintenance in the modeled year.

See also "Interaction with integer unit commitment" below.

Reduction of number of possible start dates

This module creates constraints which work across long periods, and consequently can be very expensive to solve. In order to reduce the expense, the set of possible maintenance start dates can be limited. Rather than have maintenance potentially start every hour, one can have possible start dates which are once per day, once per week, etc. (In reality, maintenance is likely scheduled months in advance, so optimizing down to the hour may not be realistic anyway.)

How to use

There are four columns which need to be added to the plant data, i.e. in Generators_data.csv:

  1. MAINT should be 1 for plants that require maintenance and 0 otherwise.
  2. Maintenance_Duration is the number of hours the maintenance period lasts.
  3. Maintenance_Cycle_Length_Years. If 1, maintenance every year, if 3 maintenance every 3 years, etc.
  4. Maintenance_Begin_Cadence. Spacing between hours in which maintenance can start.

The last three fields must be integers which are greater than 0. They are ignored for any plants which do not require maintenance.

Maintenance_Duration must be less than the total number of hours in the year.

If Maintenance_Begin_Cadence is 1 then the maintenance can begin in any hour. If it is 168 then it can begin in hours 1, 169, 337, etc.

Restrictions on use

The maintenance module has these restrictions:

  • More than a single maintenance period per year (i.e. every three months) is not possible in the current formulation.
  • Only full-year cases can be run; there must be only one "representative period".

It would not make sense to model a month-long maintenance period when the year is modeled as a series of representative weeks, for example.

Interaction with integer unit commitment

If integer unit commitment is on (UCommit=1) this module may not produce correct results; there may be more maintenance than the user wants. This is because the formulation specifies that the number of plants that go down for maintenance in the simulated year must be at least (the number of plants in the zone)/(the maintenance cycle length in years). As a reminder, the number of plants is eTotalCap / Cap_Size.

If there were three 500 MW plants (total 1500 MW) in a zone, and they require maintenance every three years (Maintenance_Cycle_Length_Years=3), the formulation will work properly: one of the three plants will go under maintenance.

But if there was only one 500 MW plant, and it requires maintenance every 3 years, the constraint will still make it do maintenance every year, because ceil(1/3) is 1. The whole 500 MW plant will do maintenance. This is the unexpected behavior.

However, if integer unit commitment was relaxed to "linearized" unit commitment (UCommit=2), the model will have only 500 MW / 3 = 166.6 MW worth of this plant do maintenance.

Hint: pre-scheduling maintenance

If you want to pre-schedule when maintenance occurs, you might not need this module. Instead, you could set the maximum power output of the plant to zero for a certain period, or make its fuel extremely expensive during that time. However, the plant would still be able to contribute to the Capacity Reserve Margin.

Outputs produced

If at least one plant has MAINT=1, a file maint_down.csv will be written listing how many plants are down for maintenance in each timestep.

Notes on mathematical formulation

The formulation of the maintenance state is very similar to the formulation of unit commitment.

There is a variable called something like vMSHUT which is analogous to vSTART and controls the start of the maintenance period. There is another variable called something like vMDOWN analogous to vCOMMIT which controls the maintenance status in any hour.

A constraint ensures that the value of vMDOWN in any hour is always more than the number of vMSHUTs in the previous Maintenance_Duration hours.

Another constraint ensures that the number of plants committed (vCOMMIT) at any one time plus the number of plants under maintenance (vMDOWN) is less than the total number of plants.

Developer note: adding maintenance to a resource

The maintenance formulation is applied on a per-resource basis, by calling the function GenX.maintenance_formulation!.

See GenX.maintenance_formulation_thermal_commit! for an example of how to apply it to a new resource.

  • The resource must have a vCOMMIT-like variable which is proportional to maximum the power output, etc at any given timestep.
  • The resource must have a eTotalCap-like quantity and a Cap_Size-like parameter; only the ratio of the two is used.
diff --git a/previews/PR655/Model_Reference/methodofmorris/index.html b/previews/PR655/Model_Reference/methodofmorris/index.html index e2789f1b5b..e626326566 100644 --- a/previews/PR655/Model_Reference/methodofmorris/index.html +++ b/previews/PR655/Model_Reference/methodofmorris/index.html @@ -1,2 +1,2 @@ -Method of Morris · GenX

Method of Morris

GenX.MatSpreadType
morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER)

We apply the Method of Morris developed by Morris, M., 1991 in order to identify the input parameters that produce the largest change on total system cost. Method of Morris falls under the simplest class of one-factor-at-a-time (OAT) screening techniques. It assumes l levels per input factor and generates a set of trajectories through the input space. As such, the Method of Morris generates a grid of uncertain model input parameters, $x_i, i=1, ..., k$,, where the range $[x_i^{-}, x_i^{+}$ of each uncertain input parameter i is split into l intervals of equal length. Each trajectory starts at different realizations of input parameters chosen at random and are built by successively selecting one of the inputs randomly and moving it to an adjacent level. These trajectories are used to estimate the mean and the standard deviation of each input parameter on total system cost. A high estimated mean indicates that the input parameter is important; a high estimated standard deviation indicates important interactions between that input parameter and other inputs.

source
+Method of Morris · GenX

Method of Morris

GenX.MatSpreadType
morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER)

We apply the Method of Morris developed by Morris, M., 1991 in order to identify the input parameters that produce the largest change on total system cost. Method of Morris falls under the simplest class of one-factor-at-a-time (OAT) screening techniques. It assumes l levels per input factor and generates a set of trajectories through the input space. As such, the Method of Morris generates a grid of uncertain model input parameters, $x_i, i=1, ..., k$,, where the range $[x_i^{-}, x_i^{+}$ of each uncertain input parameter i is split into l intervals of equal length. Each trajectory starts at different realizations of input parameters chosen at random and are built by successively selecting one of the inputs randomly and moving it to an adjacent level. These trajectories are used to estimate the mean and the standard deviation of each input parameter on total system cost. A high estimated mean indicates that the input parameter is important; a high estimated standard deviation indicates important interactions between that input parameter and other inputs.

source
diff --git a/previews/PR655/Model_Reference/mga/index.html b/previews/PR655/Model_Reference/mga/index.html index 0bec510c35..8737fb42ee 100644 --- a/previews/PR655/Model_Reference/mga/index.html +++ b/previews/PR655/Model_Reference/mga/index.html @@ -6,4 +6,4 @@ &P_{zr} = \sum_{y \in \mathcal{G}}\sum_{t \in \mathcal{T}} \omega_{t} \Theta_{y,t,z,r} \\ & f \leq f^* + \delta \\ &Ax = b -\end{aligned}\]

where, $\beta_{zr}$ is a random objective fucntion coefficient betwen $[0,100]$ for MGA iteration $k$. $\Theta_{y,t,z,r}$ is a generation of technology $y$ in zone $z$ in time period $t$ that belongs to a resource type $r$. We aggregate $\Theta_{y,t,z,r}$ into a new variable $P_{z,r}$ that represents total generation from technology type $r$ in a zone $z$. In the second constraint above, $\delta$ denote the increase in budget from the least-cost solution and $f$ represents the expression for the total system cost. The constraint $Ax = b$ represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.

source +\end{aligned}\]

where, $\beta_{zr}$ is a random objective fucntion coefficient betwen $[0,100]$ for MGA iteration $k$. $\Theta_{y,t,z,r}$ is a generation of technology $y$ in zone $z$ in time period $t$ that belongs to a resource type $r$. We aggregate $\Theta_{y,t,z,r}$ into a new variable $P_{z,r}$ that represents total generation from technology type $r$ in a zone $z$. In the second constraint above, $\delta$ denote the increase in budget from the least-cost solution and $f$ represents the expression for the total system cost. The constraint $Ax = b$ represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.

source diff --git a/previews/PR655/Model_Reference/policies/index.html b/previews/PR655/Model_Reference/policies/index.html index 35d5d069fb..ce923f8712 100644 --- a/previews/PR655/Model_Reference/policies/index.html +++ b/previews/PR655/Model_Reference/policies/index.html @@ -11,7 +11,7 @@ & + \sum_{l \in \mathcal{L}_{p}^{in}} \epsilon_{y,z,p}^{CRM} \times \Phi_{l,t} - \sum_{l \in \mathcal{L}_{p}^{out}} \epsilon_{y,z,p}^{CRM} \times \Phi_{l,t} + \sum_{s \geq 2} \Lambda_{s,t,z} \Big) \\ & \geq \sum_{z \in \mathcal{Z}^{CRM}_{p}} \left( \left(1 + RM_{z,p}^{CRM} \right) \times D_{z,t} \right) \hspace{1 cm} \forall t \in \mathcal{T}, \forall p\in \mathcal{P}^{CRM} -\end{aligned}\]

Note that multiple capacity reserve margin requirements can be specified covering different individual zones or aggregations of zones, where the total number of constraints is specified by the GenX settings parameter CapacityReserveMargin (where this parameter should be an integer value > 0). The expressions establishing the capacity reserve margin contributions of each technology class are included in their respective technology modules.

source

CO$_2$ Constraint Policy

GenX.co2_cap!Function
co2_cap!(EP::Model, inputs::Dict, setup::Dict)

This policy constraints mimics the CO$_2$ emissions cap and permit trading systems, allowing for emissions trading across each zone for which the cap applies. The constraint $p \in \mathcal{P}^{CO_2}$ can be flexibly defined for mass-based or rate-based emission limits for one or more model zones, where zones can trade CO$_2$ emissions permits and earn revenue based on their CO$_2$ allowance. Note that if the model is fully linear (e.g. no unit commitment or linearized unit commitment), the dual variable of the emissions constraints can be interpreted as the marginal CO$_2$ price per tonne associated with the emissions target. Alternatively, for integer model formulations, the marginal CO$_2$ price can be obtained after solving the model with fixed integer/binary variables.

The CO$_2$ emissions limit can be defined in one of the following ways: a) a mass-based limit defined in terms of annual CO$_2$ emissions budget (in million tonnes of CO2), b) a demand-side rate-based limit defined in terms of tonnes CO$_2$ per MWh of fulfilled demand and c) a generation-side rate-based limit defined in terms of tonnes CO$_2$ per MWh of generation.

Mass-based emissions constraint

Mass-based emission limits are implemented in the following expression. For each constraint, $p \in \mathcal{P}^{CO_2}_{mass}$, we define a set of zones $z \in \mathcal{Z}^{CO_2}_{p,mass}$ that can trade CO$_2$ allowance. Input data for each constraint $p \in \mathcal{P}^{CO_2}_{mass}$ requires the CO$_2$ allowance/ budget for each model zone, $\epsilon^{CO_{2}}_{z,p, mass}$, to be provided in terms of million metric tonnes. For every generator $y$, the parameter $\epsilon_{y,z}^{CO_2}$ reflects the specific $CO_2$ emission intensity in tCO$_2$/MWh associated with its operation. The resulting constraint is given as:

\[\begin{aligned} +\end{aligned}\]

Note that multiple capacity reserve margin requirements can be specified covering different individual zones or aggregations of zones, where the total number of constraints is specified by the GenX settings parameter CapacityReserveMargin (where this parameter should be an integer value > 0). The expressions establishing the capacity reserve margin contributions of each technology class are included in their respective technology modules.

source

CO$_2$ Constraint Policy

GenX.co2_cap!Function
co2_cap!(EP::Model, inputs::Dict, setup::Dict)

This policy constraints mimics the CO$_2$ emissions cap and permit trading systems, allowing for emissions trading across each zone for which the cap applies. The constraint $p \in \mathcal{P}^{CO_2}$ can be flexibly defined for mass-based or rate-based emission limits for one or more model zones, where zones can trade CO$_2$ emissions permits and earn revenue based on their CO$_2$ allowance. Note that if the model is fully linear (e.g. no unit commitment or linearized unit commitment), the dual variable of the emissions constraints can be interpreted as the marginal CO$_2$ price per tonne associated with the emissions target. Alternatively, for integer model formulations, the marginal CO$_2$ price can be obtained after solving the model with fixed integer/binary variables.

The CO$_2$ emissions limit can be defined in one of the following ways: a) a mass-based limit defined in terms of annual CO$_2$ emissions budget (in million tonnes of CO2), b) a demand-side rate-based limit defined in terms of tonnes CO$_2$ per MWh of fulfilled demand and c) a generation-side rate-based limit defined in terms of tonnes CO$_2$ per MWh of generation.

Mass-based emissions constraint

Mass-based emission limits are implemented in the following expression. For each constraint, $p \in \mathcal{P}^{CO_2}_{mass}$, we define a set of zones $z \in \mathcal{Z}^{CO_2}_{p,mass}$ that can trade CO$_2$ allowance. Input data for each constraint $p \in \mathcal{P}^{CO_2}_{mass}$ requires the CO$_2$ allowance/ budget for each model zone, $\epsilon^{CO_{2}}_{z,p, mass}$, to be provided in terms of million metric tonnes. For every generator $y$, the parameter $\epsilon_{y,z}^{CO_2}$ reflects the specific $CO_2$ emission intensity in tCO$_2$/MWh associated with its operation. The resulting constraint is given as:

\[\begin{aligned} \sum_{z \in \mathcal{Z}^{CO_2}_{p,mass}} \sum_{y \in \mathcal{G}} \sum_{t \in \mathcal{T}} \left(\epsilon_{y,z}^{CO_2} \times \omega_{t} \times \Theta_{y,z,t} \right) & \leq \sum_{z \in \mathcal{Z}^{CO_2}_{p,mass}} \epsilon^{CO_{2}}_{z,p, mass} \hspace{1 cm} \forall p \in \mathcal{P}^{CO_2}_{mass} \end{aligned}\]

In the above constraint, we include both power discharge and charge term for each resource to account for the potential for CO$_2$ emissions (or removal when considering negative emissions technologies) associated with each step. Note that if a limit is applied to each zone separately, then the set $\mathcal{Z}^{CO_2}_{p,mass}$ will contain only one zone with no possibility of trading. If a system-wide emission limit constraint is applied, then $\mathcal{Z}^{CO_2}_{p,mass}$ will be equivalent to a set of all zones.

Demand-side rate-based emissions constraint

We modify the right hand side of the above mass-based constraint, $p \in \mathcal{P}^{CO_2}_{demand}$, to set emissions target based on a CO$_2$ emission rate limit in tCO$_2$/MWh $\times$ the total demand served (fulfilled) in each zone. In the following constraint, total demand served takes into account non-served energy and storage related losses. Here, $\epsilon_{z,p,demand}^{maxCO_2}$ denotes the emission limit in terms on tCO$_2$/MWh.

\[\begin{aligned} @@ -24,12 +24,12 @@ \end{aligned}\]

Generator-side emissions rate-based constraint

Similarly, a generation based emission constraint is defined by setting the emission limit based on the total generation times the carbon emission rate limit in tCO$_2$/MWh of the region. The resulting constraint is given as:

\[\begin{aligned} \sum_{z \in \mathcal{Z}^{CO_2}_{p,gen}} \sum_{y \in \mathcal{G}} \sum_{t \in \mathcal{T}} & \left(\epsilon_{y,z}^{CO_2} \times \omega_{t} \times \Theta_{y,t,z} \right) \\ \leq \sum_{z \in \mathcal{Z}^{CO_2}_{p,gen}} \sum_{y \in \mathcal{G}} \sum_{t \in \mathcal{T}} & \left(\epsilon_{z,p,gen}^{CO_2} \times \omega_{t} \times \Theta_{y,t,z} \right) \hspace{1 cm} \forall p \in \mathcal{P}^{CO_2}_{gen} -\end{aligned}\]

Note that the generator-side rate-based constraint can be used to represent a fee-rebate (``feebate'') system: the dirty generators that emit above the bar ($\epsilon_{z,p,gen}^{maxCO_2}$) have to buy emission allowances from the emission regulator in the region $z$ where they are located; in the same vein, the clean generators get rebates from the emission regulator at an emission allowance price being the dual variable of the emissions rate constraint.

source

Energy Share Requirement

GenX.load_energy_share_requirement!Function
load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)

source
GenX.energy_share_requirement!Function
energy_share_requirement!(EP::Model, inputs::Dict, setup::Dict)

This function establishes constraints that can be flexibily applied to define alternative forms of policies that require generation of a minimum quantity of megawatt-hours from a set of qualifying resources, such as renewable portfolio standard (RPS) or clean electricity standard (CES) policies prevalent in different jurisdictions. These policies usually require that the annual MWh generation from a subset of qualifying generators has to be higher than a pre-specified percentage of demand from qualifying zones. The implementation allows for user to define one or multiple RPS/CES style minimum energy share constraints, where each constraint can cover different combination of model zones to mimic real-world policy implementation (e.g. multiple state policies, multiple RPS tiers or overlapping RPS and CES policies). The number of energy share requirement constraints is specified by the user by the value of the GenX settings parameter EnergyShareRequirement (this value should be an integer >=0). For each constraint $p \in \mathcal{P}^{ESR}$, we define a subset of zones $z \in \mathcal{Z}^{ESR}_{p} \subset \mathcal{Z}$ that are eligible for trading renewable/clean energy credits to meet the corresponding renewable/clean energy requirement. For each energy share requirement constraint $p \in \mathcal{P}^{ESR}$, we specify the share of total demand in each eligible model zone, $z \in \mathcal{Z}^{ESR}_{p}$, that must be served by qualifying resources, $\mathcal{G}_{p}^{ESR} \subset \mathcal{G}$:

\[\begin{aligned} +\end{aligned}\]

Note that the generator-side rate-based constraint can be used to represent a fee-rebate (``feebate'') system: the dirty generators that emit above the bar ($\epsilon_{z,p,gen}^{maxCO_2}$) have to buy emission allowances from the emission regulator in the region $z$ where they are located; in the same vein, the clean generators get rebates from the emission regulator at an emission allowance price being the dual variable of the emissions rate constraint.

source

Energy Share Requirement

GenX.load_energy_share_requirement!Function
load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)

Read input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)

source
GenX.energy_share_requirement!Function
energy_share_requirement!(EP::Model, inputs::Dict, setup::Dict)

This function establishes constraints that can be flexibily applied to define alternative forms of policies that require generation of a minimum quantity of megawatt-hours from a set of qualifying resources, such as renewable portfolio standard (RPS) or clean electricity standard (CES) policies prevalent in different jurisdictions. These policies usually require that the annual MWh generation from a subset of qualifying generators has to be higher than a pre-specified percentage of demand from qualifying zones. The implementation allows for user to define one or multiple RPS/CES style minimum energy share constraints, where each constraint can cover different combination of model zones to mimic real-world policy implementation (e.g. multiple state policies, multiple RPS tiers or overlapping RPS and CES policies). The number of energy share requirement constraints is specified by the user by the value of the GenX settings parameter EnergyShareRequirement (this value should be an integer >=0). For each constraint $p \in \mathcal{P}^{ESR}$, we define a subset of zones $z \in \mathcal{Z}^{ESR}_{p} \subset \mathcal{Z}$ that are eligible for trading renewable/clean energy credits to meet the corresponding renewable/clean energy requirement. For each energy share requirement constraint $p \in \mathcal{P}^{ESR}$, we specify the share of total demand in each eligible model zone, $z \in \mathcal{Z}^{ESR}_{p}$, that must be served by qualifying resources, $\mathcal{G}_{p}^{ESR} \subset \mathcal{G}$:

\[\begin{aligned} &\sum_{z \in \mathcal{Z}_{p}^{ESR}} \sum_{y \in \mathcal{G}_{p}^{ESR}} \sum_{t \in \mathcal{T}} (\omega_{t} \times \Theta_{y,z,t}) \geq \sum_{z \in \mathcal{Z}^{ESR}_{p}} \sum_{t \in \mathcal{T}} (\mu_{p,z}^{ESR} \times \omega_{t} \times D_{z,t}) + \\ &\sum_{y \in \mathcal{VS}^{stor}} \sum_{z \in \mathcal{Z}^{ESR}_{p}} \sum_{t \in \mathcal{T}} \left(\mu_{p,z}^{ESR} \times \omega_{t} \times (\frac{\Pi^{dc}_{y,z,t}}{\eta_{y,z}^{inverter}} + \Pi^{ac}_{y,z,t} - \eta_{y,z}^{inverter} \times \Theta^{dc}_{y,z,t} - \Theta^{ac}_{y,z,t}) \right) + \\ &\sum_{y \in \mathcal{O}} \sum_{z \in \mathcal{Z}^{ESR}_{p}} \sum_{t \in \mathcal{T}} \left(\mu_{p,z}^{ESR} \times \omega_{t} \times (\Pi_{y,z,t} - \Theta_{y,z,t}) \right) \hspace{1 cm} \forall p \in \mathcal{P}^{ESR} \\ -\end{aligned}\]

The final two terms in the summation above adds roundtrip storage losses to the total demand to which the energy share obligation applies. This term is included in the constraint if the GenX setup parameter StorageLosses=1. If StorageLosses=0, this term is removed from the constraint. In practice, most existing renewable portfolio standard policies do not account for storage losses when determining energy share requirements. However, with 100% RPS or CES policies enacted in several jurisdictions, policy makers may wish to include storage losses in the minimum energy share, as otherwise there will be a difference between total generation and total demand that will permit continued use of non-qualifying resources (e.g. emitting generators).

source

Minimum Capacity Requirement

GenX.minimum_capacity_requirement!Function
minimum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)

The minimum capacity requirement constraint allows for modeling minimum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement $p \in \mathcal{P}^{MinCapReq}$, we model the policy with the following constraint.

\[\begin{aligned} +\end{aligned}\]

The final two terms in the summation above adds roundtrip storage losses to the total demand to which the energy share obligation applies. This term is included in the constraint if the GenX setup parameter StorageLosses=1. If StorageLosses=0, this term is removed from the constraint. In practice, most existing renewable portfolio standard policies do not account for storage losses when determining energy share requirements. However, with 100% RPS or CES policies enacted in several jurisdictions, policy makers may wish to include storage losses in the minimum energy share, as otherwise there will be a difference between total generation and total demand that will permit continued use of non-qualifying resources (e.g. emitting generators).

source

Minimum Capacity Requirement

GenX.minimum_capacity_requirement!Function
minimum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)

The minimum capacity requirement constraint allows for modeling minimum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement $p \in \mathcal{P}^{MinCapReq}$, we model the policy with the following constraint.

\[\begin{aligned} \sum_{y \in \mathcal{G} } \sum_{z \in \mathcal{Z} } \left( \epsilon_{y,z,p}^{MinCapReq} \times \Delta^{\text{total}}_{y,z} \right) \geq REQ_{p}^{MinCapReq} \hspace{1 cm} \forall p \in \mathcal{P}^{MinCapReq} -\end{aligned}\]

Note that $\epsilon_{y,z,p}^{MinCapReq}$ is the eligiblity of a generator of technology $y$ in zone $z$ of requirement $p$ and will be equal to $1$ for eligible generators and will be zero for ineligible resources. The dual value of each minimum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.

Also note that co-located VRE and storage resources, there are three different components that minimum capacity requirements can be created for. The capacity of solar PV (in AC terms since the capacity is multiplied by the inverter efficiency), the capacity of wind, and the discharge capacity of storage (power to energy ratio times the energy capacity) can all have minimum capacity requirements.

source

Maximum Capacity Requirement

GenX.load_maximum_capacity_requirement!Method
load_maximum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)

Read input parameters related to maximum capacity requirement constraints (e.g. technology specific deployment mandates)

source
GenX.maximum_capacity_requirement!Method
maximum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)

The maximum capacity requirement constraint allows for modeling maximum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement $p \in \mathcal{P}^{MaxCapReq}$, we model the policy with the following constraint.

\[\begin{aligned} +\end{aligned}\]

Note that $\epsilon_{y,z,p}^{MinCapReq}$ is the eligiblity of a generator of technology $y$ in zone $z$ of requirement $p$ and will be equal to $1$ for eligible generators and will be zero for ineligible resources. The dual value of each minimum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.

Also note that co-located VRE and storage resources, there are three different components that minimum capacity requirements can be created for. The capacity of solar PV (in AC terms since the capacity is multiplied by the inverter efficiency), the capacity of wind, and the discharge capacity of storage (power to energy ratio times the energy capacity) can all have minimum capacity requirements.

source

Maximum Capacity Requirement

GenX.load_maximum_capacity_requirement!Method
load_maximum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)

Read input parameters related to maximum capacity requirement constraints (e.g. technology specific deployment mandates)

source
GenX.maximum_capacity_requirement!Method
maximum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)

The maximum capacity requirement constraint allows for modeling maximum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement $p \in \mathcal{P}^{MaxCapReq}$, we model the policy with the following constraint.

\[\begin{aligned} \sum_{y \in \mathcal{G} } \sum_{z \in \mathcal{Z} } \left( \epsilon_{y,z,p}^{MaxCapReq} \times \Delta^{\text{total}}_{y,z} \right) \leq REQ_{p}^{MaxCapReq} \hspace{1 cm} \forall p \in \mathcal{P}^{MaxCapReq} -\end{aligned}\]

Note that $\epsilon_{y,z,p}^{MaxCapReq}$ is the eligiblity of a generator of technology $y$ in zone $z$ of requirement $p$ and will be equal to $1$ for eligible generators and will be zero for ineligible resources. The dual value of each maximum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.

source
+\end{aligned}\]

Note that $\epsilon_{y,z,p}^{MaxCapReq}$ is the eligiblity of a generator of technology $y$ in zone $z$ of requirement $p$ and will be equal to $1$ for eligible generators and will be zero for ineligible resources. The dual value of each maximum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.

source diff --git a/previews/PR655/Model_Reference/solve_model/index.html b/previews/PR655/Model_Reference/solve_model/index.html index a3ab822e07..0afcdcd506 100644 --- a/previews/PR655/Model_Reference/solve_model/index.html +++ b/previews/PR655/Model_Reference/solve_model/index.html @@ -1,2 +1,2 @@ -Solving the Model · GenX

Solving the Model

GenX.fix_integersMethod
fix_integers(jump_model::Model)

This function fixes the iteger variables ones the model has been solved in order to calculate approximations of dual variables.

Arguments

  • jump_model::Model: a model object containing that has been previously solved.

Returns

nothing (modifies an existing-solved model in the memory). solve() must be run again to solve and getdual veriables

source
GenX.solve_modelMethod
solve_model(EP::Model, setup::Dict)

Description: Solves and extracts solution variables for later processing

Arguments

  • EP::Model: a JuMP model representing the energy optimization problem
  • setup::Dict: a Dict containing GenX setup flags

Returns

  • EP::Model: the solved JuMP model
  • solver_time::Float64: time taken to solve the model
source
+Solving the Model · GenX

Solving the Model

GenX.fix_integersMethod
fix_integers(jump_model::Model)

This function fixes the iteger variables ones the model has been solved in order to calculate approximations of dual variables.

Arguments

  • jump_model::Model: a model object containing that has been previously solved.

Returns

nothing (modifies an existing-solved model in the memory). solve() must be run again to solve and getdual veriables

source
GenX.solve_modelMethod
solve_model(EP::Model, setup::Dict)

Description: Solves and extracts solution variables for later processing

Arguments

  • EP::Model: a JuMP model representing the energy optimization problem
  • setup::Dict: a Dict containing GenX setup flags

Returns

  • EP::Model: the solved JuMP model
  • solver_time::Float64: time taken to solve the model
source
diff --git a/previews/PR655/Model_Reference/solver_configuration_api/index.html b/previews/PR655/Model_Reference/solver_configuration_api/index.html index 604f512926..99a29f407d 100644 --- a/previews/PR655/Model_Reference/solver_configuration_api/index.html +++ b/previews/PR655/Model_Reference/solver_configuration_api/index.html @@ -1,5 +1,5 @@ -Solver Configurations · GenX

Configuring the Solvers

GenX.configure_solverMethod
configure_solver(solver_settings_path::String, optimizer::Any)

This method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\_model() method.

Arguments

  • solver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.
  • optimizer::Any: the optimizer instance to be configured.

Currently supported solvers include: "Gurobi", "CPLEX", "Clp", "Cbc", or "SCIP"

Returns

  • optimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.
source
GenX.infer_solverMethod
infer_solver(optimizer::Any)

Return the name (String) of the solver to be used in the GenX.configure_solver method according to the solver imported by the user.

source
GenX.rename_keysMethod
rename_keys(attributes:Dict, new_key_names::Dict)

Renames the keys of the attributes dictionary based on old->new pairs in the newkeynames dictionary.

source

Configuring HiGHS

GenX.configure_highsMethod
configure_highs(solver_settings_path::String)

Reads user-specified solver settings from highs_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes HiGHS optimizer instance to be used in the GenX.generate_model() method.

The HiGHS optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided: All the references are in https://github.com/jump-dev/HiGHS.jl, https://github.com/ERGO-Code/HiGHS, and https://highs.dev/

# HiGHS Solver Parameters
+Solver Configurations · GenX

Configuring the Solvers

GenX.configure_solverMethod
configure_solver(solver_settings_path::String, optimizer::Any)

This method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\_model() method.

Arguments

  • solver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.
  • optimizer::Any: the optimizer instance to be configured.

Currently supported solvers include: "Gurobi", "CPLEX", "Clp", "Cbc", or "SCIP"

Returns

  • optimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.
source
GenX.infer_solverMethod
infer_solver(optimizer::Any)

Return the name (String) of the solver to be used in the GenX.configure_solver method according to the solver imported by the user.

source
GenX.rename_keysMethod
rename_keys(attributes:Dict, new_key_names::Dict)

Renames the keys of the attributes dictionary based on old->new pairs in the newkeynames dictionary.

source

Configuring HiGHS

GenX.configure_highsMethod
configure_highs(solver_settings_path::String)

Reads user-specified solver settings from highs_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes HiGHS optimizer instance to be used in the GenX.generate_model() method.

The HiGHS optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided: All the references are in https://github.com/jump-dev/HiGHS.jl, https://github.com/ERGO-Code/HiGHS, and https://highs.dev/

# HiGHS Solver Parameters
 # Common solver settings
 Feasib_Tol: 1.0e-06        # Primal feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]
 Optimal_Tol: 1.0e-03       # Dual feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]
@@ -318,4 +318,4 @@
 
 Use LiDSE if LP has right properties
 [type: bool, advanced: true, range: {false, true}, default: true]
-less_infeasible_DSE_choose_row: true
source

Configuring Gurobi

GenX.configure_gurobiMethod
configure_gurobi(solver_settings_path::String)

Reads user-specified solver settings from gurobi_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes Gurobi optimizer instance to be used in the GenX.generate_model() method.

The Gurobi optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • FeasibilityTol = 1e-6 (Constraint (primal) feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/feasibilitytol.html)
  • OptimalityTol = 1e-4 (Dual feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/optimalitytol.html#parameter:OptimalityTol)
  • Presolve = -1 (Controls presolve level. See https://www.gurobi.com/documentation/8.1/refman/presolve.html)
  • AggFill = -1 (Allowed fill during presolve aggregation. See https://www.gurobi.com/documentation/8.1/refman/aggfill.html#parameter:AggFill)
  • PreDual = -1 (Presolve dualization. See https://www.gurobi.com/documentation/8.1/refman/predual.html#parameter:PreDual)
  • TimeLimit = Inf (Limits total time solver. See https://www.gurobi.com/documentation/8.1/refman/timelimit.html)
  • MIPGap = 1e-4 (Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). See https://www.gurobi.com/documentation/8.1/refman/mipgap2.html)
  • Crossover = -1 (Barrier crossver strategy. See https://www.gurobi.com/documentation/8.1/refman/crossover.html#parameter:Crossover)
  • Method = -1 (Algorithm used to solve continuous models (including MIP root relaxation). See https://www.gurobi.com/documentation/8.1/refman/method.html)
  • BarConvTol = 1e-8 (Barrier convergence tolerance (determines when barrier terminates). See https://www.gurobi.com/documentation/8.1/refman/barconvtol.html)
  • NumericFocus = 0 (Numerical precision emphasis. See https://www.gurobi.com/documentation/8.1/refman/numericfocus.html)
source

Configuring CPLEX

GenX.configure_cplexMethod
configure_cplex(solver_settings_path::String)

Reads user-specified solver settings from cplex_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes CPLEX optimizer instance.

The optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • Feasib_Tol,

    sets CPX_PARAM_EPRHS. Control the primal feasibility tolerance. Default is 1e-6.

  • Optimal_Tol,

    sets CPX_PARAM_EPOPT. Control the optimality tolerance. Default is 1e-4.

  • AggFill,

    sets CPX_PARAM_AGGFILL. Control the allowed fill during presolve aggregation. Default is 10.

  • PreDual,

    sets CPX_PARAM_PREDUAL. Decides whether presolve should pass the primal or dual linear programming problem to the LP optimization algorithm. Default is 0.

  • TimeLimit,

    sets CPX_PARAM_TILIM. Limits total solver time. Default is 1e+75.

  • MIPGap,

    sets CPX_PARAM_EPGAP Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). Default is 1e-3.

  • Method,

    sets CPX_PARAM_LPMETHOD. Algorithm used to solve continuous models (including MIP root relaxation) Default is 0.

  • BarConvTol,

    sets CPX_PARAM_BAREPCOMP. Barrier convergence tolerance (determines when barrier terminates). Default is 1e-8.

  • NumericFocus,

    sets CPX_PARAM_NUMERICALEMPHASIS. Numerical precision emphasis. Default is 0.

  • BarObjRng,

    sets CPX_PARAM_BAROBJRNG. The maximum absolute value of the objective function. Default is 1e+75.

  • SolutionType,

    sets CPX_PARAM_SOLUTIONTYPE. Solution type for LP or QP. Default is 2.

The optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

Any other attributes in the settings file (which typically start with CPX_PARAM_) will also be passed to the solver.

source

Configuring Clp

GenX.configure_clpMethod
configure_clp(solver_settings_path::String)

Reads user-specified solver settings from clp_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes Clp optimizer instance to be used in the GenX.generate_model() method.

The Clp optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • PrimalTolerance = 1e-7 (Primal feasibility tolerance)
  • DualTolerance = 1e-7 (Dual feasibility tolerance)
  • DualObjectiveLimit = 1e308 (When using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit)
  • MaximumIterations = 2147483647 (Terminate after performing this number of simplex iterations)
  • MaximumSeconds = -1.0 (Terminate after this many seconds have passed. A negative value means no time limit)
  • LogLevel = 1 (Set to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output)
  • PresolveType = 0 (Set to 1 to disable presolve)
  • SolveType = 5 (Solution method: dual simplex (0), primal simplex (1), sprint (2), barrier with crossover (3), barrier without crossover (4), automatic (5))
  • InfeasibleReturn = 0 (Set to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well))
  • Scaling = 3 (0 0ff, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic (later))
  • Perturbation = 100 (switch on perturbation (50), automatic (100), don't try perturbing (102))
source

Configuring Cbc

GenX.configure_cbcMethod
configure_cbc(solver_settings_path::String)

Reads user-specified solver settings from cbc_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes Cbc optimizer instance to be used in the GenX.generate_model() method.

The Cbc optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • seconds = 1e-6
  • logLevel = 1e-6
  • maxSolutions = -1
  • maxNodes = -1
  • allowableGap = -1
  • ratioGap = Inf
  • threads = 1
source

Configuring SCIP

GenX.configure_scipMethod
configure_scip(solver_settings_path::String)

Reads user-specified solver settings from scip_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes SCIP optimizer instance to be used in the GenX.generate_model() method.

The SCIP optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • Dispverblevel = 0
  • limitsgap = 0.05
source
+less_infeasible_DSE_choose_row: true
source

Configuring Gurobi

GenX.configure_gurobiMethod
configure_gurobi(solver_settings_path::String)

Reads user-specified solver settings from gurobi_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes Gurobi optimizer instance to be used in the GenX.generate_model() method.

The Gurobi optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • FeasibilityTol = 1e-6 (Constraint (primal) feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/feasibilitytol.html)
  • OptimalityTol = 1e-4 (Dual feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/optimalitytol.html#parameter:OptimalityTol)
  • Presolve = -1 (Controls presolve level. See https://www.gurobi.com/documentation/8.1/refman/presolve.html)
  • AggFill = -1 (Allowed fill during presolve aggregation. See https://www.gurobi.com/documentation/8.1/refman/aggfill.html#parameter:AggFill)
  • PreDual = -1 (Presolve dualization. See https://www.gurobi.com/documentation/8.1/refman/predual.html#parameter:PreDual)
  • TimeLimit = Inf (Limits total time solver. See https://www.gurobi.com/documentation/8.1/refman/timelimit.html)
  • MIPGap = 1e-4 (Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). See https://www.gurobi.com/documentation/8.1/refman/mipgap2.html)
  • Crossover = -1 (Barrier crossver strategy. See https://www.gurobi.com/documentation/8.1/refman/crossover.html#parameter:Crossover)
  • Method = -1 (Algorithm used to solve continuous models (including MIP root relaxation). See https://www.gurobi.com/documentation/8.1/refman/method.html)
  • BarConvTol = 1e-8 (Barrier convergence tolerance (determines when barrier terminates). See https://www.gurobi.com/documentation/8.1/refman/barconvtol.html)
  • NumericFocus = 0 (Numerical precision emphasis. See https://www.gurobi.com/documentation/8.1/refman/numericfocus.html)
source

Configuring CPLEX

GenX.configure_cplexMethod
configure_cplex(solver_settings_path::String)

Reads user-specified solver settings from cplex_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes CPLEX optimizer instance.

The optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • Feasib_Tol,

    sets CPX_PARAM_EPRHS. Control the primal feasibility tolerance. Default is 1e-6.

  • Optimal_Tol,

    sets CPX_PARAM_EPOPT. Control the optimality tolerance. Default is 1e-4.

  • AggFill,

    sets CPX_PARAM_AGGFILL. Control the allowed fill during presolve aggregation. Default is 10.

  • PreDual,

    sets CPX_PARAM_PREDUAL. Decides whether presolve should pass the primal or dual linear programming problem to the LP optimization algorithm. Default is 0.

  • TimeLimit,

    sets CPX_PARAM_TILIM. Limits total solver time. Default is 1e+75.

  • MIPGap,

    sets CPX_PARAM_EPGAP Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). Default is 1e-3.

  • Method,

    sets CPX_PARAM_LPMETHOD. Algorithm used to solve continuous models (including MIP root relaxation) Default is 0.

  • BarConvTol,

    sets CPX_PARAM_BAREPCOMP. Barrier convergence tolerance (determines when barrier terminates). Default is 1e-8.

  • NumericFocus,

    sets CPX_PARAM_NUMERICALEMPHASIS. Numerical precision emphasis. Default is 0.

  • BarObjRng,

    sets CPX_PARAM_BAROBJRNG. The maximum absolute value of the objective function. Default is 1e+75.

  • SolutionType,

    sets CPX_PARAM_SOLUTIONTYPE. Solution type for LP or QP. Default is 2.

The optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

Any other attributes in the settings file (which typically start with CPX_PARAM_) will also be passed to the solver.

source

Configuring Clp

GenX.configure_clpMethod
configure_clp(solver_settings_path::String)

Reads user-specified solver settings from clp_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes Clp optimizer instance to be used in the GenX.generate_model() method.

The Clp optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • PrimalTolerance = 1e-7 (Primal feasibility tolerance)
  • DualTolerance = 1e-7 (Dual feasibility tolerance)
  • DualObjectiveLimit = 1e308 (When using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit)
  • MaximumIterations = 2147483647 (Terminate after performing this number of simplex iterations)
  • MaximumSeconds = -1.0 (Terminate after this many seconds have passed. A negative value means no time limit)
  • LogLevel = 1 (Set to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output)
  • PresolveType = 0 (Set to 1 to disable presolve)
  • SolveType = 5 (Solution method: dual simplex (0), primal simplex (1), sprint (2), barrier with crossover (3), barrier without crossover (4), automatic (5))
  • InfeasibleReturn = 0 (Set to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well))
  • Scaling = 3 (0 0ff, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic (later))
  • Perturbation = 100 (switch on perturbation (50), automatic (100), don't try perturbing (102))
source

Configuring Cbc

GenX.configure_cbcMethod
configure_cbc(solver_settings_path::String)

Reads user-specified solver settings from cbc_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes Cbc optimizer instance to be used in the GenX.generate_model() method.

The Cbc optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • seconds = 1e-6
  • logLevel = 1e-6
  • maxSolutions = -1
  • maxNodes = -1
  • allowableGap = -1
  • ratioGap = Inf
  • threads = 1
source

Configuring SCIP

GenX.configure_scipMethod
configure_scip(solver_settings_path::String)

Reads user-specified solver settings from scip_settings.yml in the directory specified by the string solver_settings_path.

Returns a MathOptInterface.OptimizerWithAttributes SCIP optimizer instance to be used in the GenX.generate_model() method.

The SCIP optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

  • Dispverblevel = 0
  • limitsgap = 0.05
source
diff --git a/previews/PR655/Model_Reference/utility_functions/index.html b/previews/PR655/Model_Reference/utility_functions/index.html index c5ec73785d..9c26c446fc 100644 --- a/previews/PR655/Model_Reference/utility_functions/index.html +++ b/previews/PR655/Model_Reference/utility_functions/index.html @@ -1,4 +1,4 @@ -Utility Functions · GenX

Utility Functions

GenX.by_rid_resMethod
by_rid_res(rid::Integer, sym::Symbol, rs::Vector{<:AbstractResource})
+Utility Functions · GenX

Utility Functions

GenX.by_rid_resMethod
by_rid_res(rid::Integer, sym::Symbol, rs::Vector{<:AbstractResource})
 
-This function returns the value of the attribute `sym` for the resource given by the ID `rid`.
source
GenX.hoursafterMethod
hoursafter(p::Int, t::Int, a::Int)

Determines the time index a hours after index t in a landscape starting from t=1 which is separated into distinct periods of length p.

For example, if p = 10, 1 hour after t=9 is t=10, 1 hour after t=10 is t=1, 1 hour after t=11 is t=2

source
GenX.hoursafterMethod
hoursafter(p::Int, t::Int, b::UnitRange)

This is a generalization of hoursafter(... b::Int) to allow for example a=1:3 to fetch a Vector{Int} of the three hours after time index t.

source
GenX.hoursbeforeMethod
hoursbefore(p::Int, t::Int, b::Int)

Determines the time index b hours before index t in a landscape starting from t=1 which is separated into distinct periods of length p.

For example, if p = 10, 1 hour before t=1 is t=10, 1 hour before t=10 is t=9 1 hour before t=11 is t=20

source
GenX.hoursbeforeMethod
hoursbefore(p::Int, t::Int, b::UnitRange)

This is a generalization of hoursbefore(... b::Int) to allow for example b=1:3 to fetch a Vector{Int} of the three hours before time index t.

source
GenX.is_nonzeroMethod
is_nonzero(df::DataFrame, col::Symbol)::BitVector

This function checks if a column in a dataframe is all zeros.

source
+This function returns the value of the attribute `sym` for the resource given by the ID `rid`.
source
GenX.hoursafterMethod
hoursafter(p::Int, t::Int, a::Int)

Determines the time index a hours after index t in a landscape starting from t=1 which is separated into distinct periods of length p.

For example, if p = 10, 1 hour after t=9 is t=10, 1 hour after t=10 is t=1, 1 hour after t=11 is t=2

source
GenX.hoursafterMethod
hoursafter(p::Int, t::Int, b::UnitRange)

This is a generalization of hoursafter(... b::Int) to allow for example a=1:3 to fetch a Vector{Int} of the three hours after time index t.

source
GenX.hoursbeforeMethod
hoursbefore(p::Int, t::Int, b::Int)

Determines the time index b hours before index t in a landscape starting from t=1 which is separated into distinct periods of length p.

For example, if p = 10, 1 hour before t=1 is t=10, 1 hour before t=10 is t=9 1 hour before t=11 is t=20

source
GenX.hoursbeforeMethod
hoursbefore(p::Int, t::Int, b::UnitRange)

This is a generalization of hoursbefore(... b::Int) to allow for example b=1:3 to fetch a Vector{Int} of the three hours before time index t.

source
GenX.is_nonzeroMethod
is_nonzero(df::DataFrame, col::Symbol)::BitVector

This function checks if a column in a dataframe is all zeros.

source
diff --git a/previews/PR655/Model_Reference/write_outputs/index.html b/previews/PR655/Model_Reference/write_outputs/index.html index 0dcf8a0080..71484ecda0 100644 --- a/previews/PR655/Model_Reference/write_outputs/index.html +++ b/previews/PR655/Model_Reference/write_outputs/index.html @@ -1,6 +1,6 @@ -Outputs Functions · GenX

Functions for Writing the Different Results/Outputs to Separate Files

GenX.write_annualMethod
write_annual(fullpath::AbstractString, dfOut::DataFrame)

Internal function for writing annual outputs.

source
GenX.write_fulltimeseriesMethod
write_fulltimeseries(fullpath::AbstractString, dataOut::Matrix{Float64}, dfOut::DataFrame)

Internal function for writing full time series outputs. This function wraps the instructions for creating the full time series output files.

source
GenX.write_outputsMethod
write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

Function for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.

source
GenX.choose_output_dirMethod
path = choose_output_dir(pathinit)

Avoid overwriting (potentially important) existing results by appending to the directory name

Checks if the suggested output directory already exists. While yes, it appends _1, _2, etc till an unused name is found

source
GenX.dftransposeMethod

df = dftranspose(df::DataFrame, withhead::Bool)

Returns a transpose of a Dataframe.

FIXME: This is for DataFrames@0.20.2, as used in GenX. Versions 0.21+ could use stack and unstack to make further changes while retaining the order

source

Write Status

GenX.write_statusMethod
write_status(path::AbstractString, inputs::Dict, EP::Model)

Function for writing the final solve status of the optimization problem solved.

source

Write CO_2 Cap

GenX.write_co2_capFunction
write_co2_cap(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting carbon price associated with carbon cap constraints.

source

Write Costs

GenX.write_costsMethod
write_costs(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the costs pertaining to the objective function (fixed, variable O&M etc.).

source

Write Fuel Consumption

GenX.write_fuel_consumptionFunction
write_fuel_consumption(path::AbstractString, inputs::Dict, setup::Dict, EP::Model).

Write fuel consumption of each power plant.

source

Write Emissions

GenX.write_emissionsMethod
write_emissions(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting time-dependent CO$_2$ emissions by zone.

source

Write Capacities

GenX.write_capacityMethod
write_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model))

Function for writing the diferent capacities for the different generation technologies (starting capacities or, existing capacities, retired capacities, and new-built capacities).

source

Write Capacity Value # TODO: add it

GenX.capacity_reserve_margin_priceMethod
capacity_reserve_margin_price(EP::Model,
+Outputs Functions · GenX

Functions for Writing the Different Results/Outputs to Separate Files

GenX.write_annualMethod
write_annual(fullpath::AbstractString, dfOut::DataFrame)

Internal function for writing annual outputs.

source
GenX.write_fulltimeseriesMethod
write_fulltimeseries(fullpath::AbstractString, dataOut::Matrix{Float64}, dfOut::DataFrame)

Internal function for writing full time series outputs. This function wraps the instructions for creating the full time series output files.

source
GenX.write_outputsMethod
write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

Function for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.

source
GenX.choose_output_dirMethod
path = choose_output_dir(pathinit)

Avoid overwriting (potentially important) existing results by appending to the directory name

Checks if the suggested output directory already exists. While yes, it appends _1, _2, etc till an unused name is found

source
GenX.dftransposeMethod

df = dftranspose(df::DataFrame, withhead::Bool)

Returns a transpose of a Dataframe.

FIXME: This is for DataFrames@0.20.2, as used in GenX. Versions 0.21+ could use stack and unstack to make further changes while retaining the order

source

Write Status

GenX.write_statusMethod
write_status(path::AbstractString, inputs::Dict, EP::Model)

Function for writing the final solve status of the optimization problem solved.

source

Write CO_2 Cap

GenX.write_co2_capFunction
write_co2_cap(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting carbon price associated with carbon cap constraints.

source

Write Costs

GenX.write_costsMethod
write_costs(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the costs pertaining to the objective function (fixed, variable O&M etc.).

source

Write Fuel Consumption

GenX.write_fuel_consumptionFunction
write_fuel_consumption(path::AbstractString, inputs::Dict, setup::Dict, EP::Model).

Write fuel consumption of each power plant.

source

Write Emissions

GenX.write_emissionsMethod
write_emissions(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting time-dependent CO$_2$ emissions by zone.

source

Write Capacities

GenX.write_capacityMethod
write_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model))

Function for writing the diferent capacities for the different generation technologies (starting capacities or, existing capacities, retired capacities, and new-built capacities).

source

Write Capacity Value # TODO: add it

GenX.capacity_reserve_margin_priceMethod
capacity_reserve_margin_price(EP::Model,
                               inputs::Dict,
                               setup::Dict,
-                              capres_zone::Int)::Vector{Float64}

Marginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.

Returns a vector, with units of $/MW
source

Write Capacity Factors

GenX.write_capacityfactorMethod
write_capacityfactor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the capacity factor of different resources. For co-located VRE-storage resources, this value is calculated if the site has either or both a solar PV or wind resource.

source

Write Charge Values

GenX.write_chargeMethod
write_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the charging energy values of the different storage technologies.

source

Write Non-served-energy

GenX.write_nseMethod
write_nse(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting non-served energy for every model zone, time step and cost-segment.

source

Write Storage State of Charge

GenX.write_storageMethod
write_storage(path::AbstractString, inputs::Dict,setup::Dict, EP::Model)

Function for writing the capacities of different storage technologies, including hydro reservoir, flexible storage tech etc.

source

Write Storage Dual

GenX.write_storagedualMethod
write_storagedual(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting dual of storage level (state of charge) balance of each resource in each time step.

source

Write Power

GenX.write_powerMethod
write_power(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the different values of power generated by the different technologies in operation.

source

Write Curtailment

GenX.write_curtailmentMethod
write_curtailment(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the curtailment values of the different variable renewable resources (both standalone and co-located).

source

Write Prices

GenX.locational_marginal_priceMethod
locational_marginal_price(EP::Model, inputs::Dict, setup::Dict)

Marginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.

Returns a matrix of size (T, Z).
-Values have units of $/MWh
source
GenX.write_priceMethod
write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the power balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.

source

Write Reliability

GenX.write_reliabilityMethod
write_reliability(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.

source

Write Energy Revenue

GenX.write_energy_revenueMethod
write_energy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing energy revenue from the different generation technologies.

source

Write Subsidy Revenue

GenX.write_subsidy_revenueMethod
write_subsidy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting subsidy revenue earned if a generator specified Min_Cap is provided in the input file, or if a generator is subject to a Minimum Capacity Requirement constraint. The unit is $.

source

Write Operating Reserve and Regulation Revenue

GenX.write_operating_reserve_regulation_revenueMethod
write_operating_reserve_regulation_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the operating reserve and regulation revenue earned by generators listed in the input file. GenX will print this file only when operating reserve and regulation are modeled and the shadow price can be obtained from the solver. The revenues are calculated as the operating reserve and regulation contributions in each time step multiplied by the corresponding shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all operating reserve and regulation constraints. As a reminder, GenX models the operating reserve and regulation at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

source

Write Capacity Revenue

GenX.write_reserve_margin_revenueMethod
write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

source

Write Energy Share Requirement Revenue

GenX.write_esr_revenueMethod
write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPower::DataFrame, dfESR::DataFrame, EP::Model)

Function for reporting the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.

source

Write Net Revenue

GenX.write_net_revenueMethod
write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model, dfCap::DataFrame, dfESRRev::DataFrame, dfResRevenue::DataFrame, dfChargingcost::DataFrame, dfPower::DataFrame, dfEnergyRevenue::DataFrame, dfSubRevenue::DataFrame, dfRegSubRevenue::DataFrame, dfVreStor::DataFrame, dfOpRegRevenue::DataFrame, dfOpRsvRevenue::DataFrame)

Function for writing net revenue of different generation technologies.

source

Write Co-Located VRE and Storage files

GenX.write_vre_storFunction
write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage specific files.

source
GenX.write_vre_stor_capacityFunction
write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage capacities.

source
GenX.write_vre_stor_chargeFunction
write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage charging decision variables/expressions.

source
GenX.write_vre_stor_dischargeFunction
write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage discharging decision variables/expressions.

source

Write Multi-stage files

GenX.write_multi_stage_costsFunction
write_multi_stage_costs(outpath::String, settings_d::Dict)

This function writes the file costs_multi_stage.csv to the Results directory. This file contains variable, fixed, startup, network expansion, unmet reserve, and non-served energy costs discounted to year zero.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_statsFunction

writemultistagestats(outpath::String, statsd::Dict)

This function writes the file stats_multi_stage.csv. to the Results directory. This file contains the runtime, upper bound, lower bound, and relative optimality gap for each iteration of the DDP algorithm.

inputs:

  • outpath – String which represents the path to the Results directory.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
source
GenX.write_multi_stage_settingsFunction
write_multi_stage_settings(outpath::AbstractString, settings_d::Dict)

Function for writing the multi-stage settings file to the output path for future reference.

source
GenX.write_multi_stage_network_expansionFunction
write_multi_stage_network_expansion(outpath::String, settings_d::Dict)

This function writes the file network_expansion_multi_stage.csv to the Results directory. This file contains new transmission capacities for each modeled transmission line for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_chargeFunction
write_multi_stage_capacities_charge(outpath::String, settings_d::Dict)

This function writes the file capacities_charge_multi_stage.csv to the Results directory. This file contains starting resource charge capacities from the first model stage and end resource charge capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_energyFunction
write_multi_stage_capacities_energy(outpath::String, settings_d::Dict)

This function writes the file capacities_energy_multi_stage.csv to the Results directory. This file contains starting resource energy capacities from the first model stage and end resource energy capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source

Write maintenance files

Write DCOPF files

GenX.write_anglesFunction
write_angles(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the bus angles for each model zone and time step if the DC_OPF flag is activated

source

Write Settings files

+ capres_zone::Int)::Vector{Float64}

Marginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.

Returns a vector, with units of $/MW
source

Write Capacity Factors

GenX.write_capacityfactorMethod
write_capacityfactor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the capacity factor of different resources. For co-located VRE-storage resources, this value is calculated if the site has either or both a solar PV or wind resource.

source

Write Charge Values

GenX.write_chargeMethod
write_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the charging energy values of the different storage technologies.

source

Write Non-served-energy

GenX.write_nseMethod
write_nse(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting non-served energy for every model zone, time step and cost-segment.

source

Write Storage State of Charge

GenX.write_storageMethod
write_storage(path::AbstractString, inputs::Dict,setup::Dict, EP::Model)

Function for writing the capacities of different storage technologies, including hydro reservoir, flexible storage tech etc.

source

Write Storage Dual

GenX.write_storagedualMethod
write_storagedual(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting dual of storage level (state of charge) balance of each resource in each time step.

source

Write Power

GenX.write_powerMethod
write_power(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the different values of power generated by the different technologies in operation.

source

Write Curtailment

GenX.write_curtailmentMethod
write_curtailment(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the curtailment values of the different variable renewable resources (both standalone and co-located).

source

Write Prices

GenX.locational_marginal_priceMethod
locational_marginal_price(EP::Model, inputs::Dict, setup::Dict)

Marginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.

Returns a matrix of size (T, Z).
+Values have units of $/MWh
source
GenX.write_priceMethod
write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the power balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.

source

Write Reliability

GenX.write_reliabilityMethod
write_reliability(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.

source

Write Energy Revenue

GenX.write_energy_revenueMethod
write_energy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing energy revenue from the different generation technologies.

source

Write Subsidy Revenue

GenX.write_subsidy_revenueMethod
write_subsidy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting subsidy revenue earned if a generator specified Min_Cap is provided in the input file, or if a generator is subject to a Minimum Capacity Requirement constraint. The unit is $.

source

Write Operating Reserve and Regulation Revenue

GenX.write_operating_reserve_regulation_revenueMethod
write_operating_reserve_regulation_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the operating reserve and regulation revenue earned by generators listed in the input file. GenX will print this file only when operating reserve and regulation are modeled and the shadow price can be obtained from the solver. The revenues are calculated as the operating reserve and regulation contributions in each time step multiplied by the corresponding shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all operating reserve and regulation constraints. As a reminder, GenX models the operating reserve and regulation at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

source

Write Capacity Revenue

GenX.write_reserve_margin_revenueMethod
write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

source

Write Energy Share Requirement Revenue

GenX.write_esr_revenueMethod
write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPower::DataFrame, dfESR::DataFrame, EP::Model)

Function for reporting the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.

source

Write Net Revenue

GenX.write_net_revenueMethod
write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model, dfCap::DataFrame, dfESRRev::DataFrame, dfResRevenue::DataFrame, dfChargingcost::DataFrame, dfPower::DataFrame, dfEnergyRevenue::DataFrame, dfSubRevenue::DataFrame, dfRegSubRevenue::DataFrame, dfVreStor::DataFrame, dfOpRegRevenue::DataFrame, dfOpRsvRevenue::DataFrame)

Function for writing net revenue of different generation technologies.

source

Write Co-Located VRE and Storage files

GenX.write_vre_storFunction
write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage specific files.

source
GenX.write_vre_stor_capacityFunction
write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage capacities.

source
GenX.write_vre_stor_chargeFunction
write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage charging decision variables/expressions.

source
GenX.write_vre_stor_dischargeFunction
write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for writing the vre-storage discharging decision variables/expressions.

source

Write Multi-stage files

GenX.write_multi_stage_costsFunction
write_multi_stage_costs(outpath::String, settings_d::Dict)

This function writes the file costs_multi_stage.csv to the Results directory. This file contains variable, fixed, startup, network expansion, unmet reserve, and non-served energy costs discounted to year zero.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_statsFunction

writemultistagestats(outpath::String, statsd::Dict)

This function writes the file stats_multi_stage.csv. to the Results directory. This file contains the runtime, upper bound, lower bound, and relative optimality gap for each iteration of the DDP algorithm.

inputs:

  • outpath – String which represents the path to the Results directory.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
source
GenX.write_multi_stage_settingsFunction
write_multi_stage_settings(outpath::AbstractString, settings_d::Dict)

Function for writing the multi-stage settings file to the output path for future reference.

source
GenX.write_multi_stage_network_expansionFunction
write_multi_stage_network_expansion(outpath::String, settings_d::Dict)

This function writes the file network_expansion_multi_stage.csv to the Results directory. This file contains new transmission capacities for each modeled transmission line for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_chargeFunction
write_multi_stage_capacities_charge(outpath::String, settings_d::Dict)

This function writes the file capacities_charge_multi_stage.csv to the Results directory. This file contains starting resource charge capacities from the first model stage and end resource charge capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source
GenX.write_multi_stage_capacities_energyFunction
write_multi_stage_capacities_energy(outpath::String, settings_d::Dict)

This function writes the file capacities_energy_multi_stage.csv to the Results directory. This file contains starting resource energy capacities from the first model stage and end resource energy capacities for the first and all subsequent model stages.

inputs:

  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
source

Write maintenance files

Write DCOPF files

GenX.write_anglesFunction
write_angles(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)

Function for reporting the bus angles for each model zone and time step if the DC_OPF flag is activated

source

Write Settings files

diff --git a/previews/PR655/Public_API/public_api/index.html b/previews/PR655/Public_API/public_api/index.html index 8a5d15447a..20b01ba04f 100644 --- a/previews/PR655/Public_API/public_api/index.html +++ b/previews/PR655/Public_API/public_api/index.html @@ -1,5 +1,5 @@ -Public API · GenX

Public Documentation

Documentation for GenX public interface.

GenX.run_genx_case!Function
run_genx_case!(case::AbstractString, optimizer::Any=HiGHS.Optimizer)

Run a GenX case with the specified optimizer. The optimizer can be any solver supported by MathOptInterface.

Arguments

  • case::AbstractString: the path to the case folder
  • optimizer::Any: the optimizer instance to be used in the optimization model

Example

run_genx_case!("path/to/case", HiGHS.Optimizer)
run_genx_case!("path/to/case", Gurobi.Optimizer)
source
GenX.configure_settingsFunction
configure_settings(settings_path::String, output_settings_path::String)

Reads in the settings from the genx_settings.yml and output_settings.yml YAML files and merges them with the default settings. It then validates the settings and returns the settings dictionary.

Arguments

  • settings_path::String: The path to the settings YAML file.
  • output_settings_path::String: The path to the output settings YAML file.

Returns

  • settings::Dict: The settings dictionary.
source
GenX.configure_solverFunction
configure_solver(solver_settings_path::String, optimizer::Any)

This method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\_model() method.

Arguments

  • solver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.
  • optimizer::Any: the optimizer instance to be configured.

Currently supported solvers include: "Gurobi", "CPLEX", "Clp", "Cbc", or "SCIP"

Returns

  • optimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.
source
GenX.load_inputsFunction
load_inputs(setup::Dict,path::AbstractString)

Loads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function

inputs: setup - dict object containing setup parameters path - string path to working directory

returns: Dict (dictionary) object containing all data inputs

source
GenX.load_dataframeFunction
load_dataframe(path::AbstractString)

Attempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.

source
load_dataframe(dir::AbstractString, base::AbstractString)

Attempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.

source
GenX.generate_modelFunction
generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAttributes,modeloutput = nothing)

This function sets up and solves a constrained optimization model of electricity system capacity expansion and operation problem and extracts solution variables for later processing.

In addition to calling a number of other modules to create constraints for specific resources, policies, and transmission assets, this function initializes two key expressions that are successively expanded in each of the resource-specific modules: (1) the objective function; and (2) the zonal power balance expression. These two expressions are the only expressions which link together individual modules (e.g. resources, transmission assets, policies), which otherwise are self-contained in defining relevant variables, expressions, and constraints.

Objective Function

The objective function of GenX minimizes total annual electricity system costs over the following six components shown in the equation below:

\[\begin{aligned} +Public API · GenX

Public Documentation

Documentation for GenX public interface.

GenX.run_genx_case!Function
run_genx_case!(case::AbstractString, optimizer::Any=HiGHS.Optimizer)

Run a GenX case with the specified optimizer. The optimizer can be any solver supported by MathOptInterface.

Arguments

  • case::AbstractString: the path to the case folder
  • optimizer::Any: the optimizer instance to be used in the optimization model

Example

run_genx_case!("path/to/case", HiGHS.Optimizer)
run_genx_case!("path/to/case", Gurobi.Optimizer)
source
GenX.configure_settingsFunction
configure_settings(settings_path::String, output_settings_path::String)

Reads in the settings from the genx_settings.yml and output_settings.yml YAML files and merges them with the default settings. It then validates the settings and returns the settings dictionary.

Arguments

  • settings_path::String: The path to the settings YAML file.
  • output_settings_path::String: The path to the output settings YAML file.

Returns

  • settings::Dict: The settings dictionary.
source
GenX.configure_solverFunction
configure_solver(solver_settings_path::String, optimizer::Any)

This method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\_model() method.

Arguments

  • solver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.
  • optimizer::Any: the optimizer instance to be configured.

Currently supported solvers include: "Gurobi", "CPLEX", "Clp", "Cbc", or "SCIP"

Returns

  • optimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.
source
GenX.load_inputsFunction
load_inputs(setup::Dict,path::AbstractString)

Loads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function

inputs: setup - dict object containing setup parameters path - string path to working directory

returns: Dict (dictionary) object containing all data inputs

source
GenX.load_dataframeFunction
load_dataframe(path::AbstractString)

Attempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.

source
load_dataframe(dir::AbstractString, base::AbstractString)

Attempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.

source
GenX.generate_modelFunction
generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAttributes,modeloutput = nothing)

This function sets up and solves a constrained optimization model of electricity system capacity expansion and operation problem and extracts solution variables for later processing.

In addition to calling a number of other modules to create constraints for specific resources, policies, and transmission assets, this function initializes two key expressions that are successively expanded in each of the resource-specific modules: (1) the objective function; and (2) the zonal power balance expression. These two expressions are the only expressions which link together individual modules (e.g. resources, transmission assets, policies), which otherwise are self-contained in defining relevant variables, expressions, and constraints.

Objective Function

The objective function of GenX minimizes total annual electricity system costs over the following six components shown in the equation below:

\[\begin{aligned} &\sum_{y \in \mathcal{G} } \sum_{z \in \mathcal{Z}} \left( (\pi^{INVEST}_{y,z} \times \overline{\Omega}^{size}_{y,z} \times \Omega_{y,z}) + (\pi^{FOM}_{y,z} \times \overline{\Omega}^{size}_{y,z} \times \Delta^{total}_{y,z})\right) + \notag \\ @@ -18,11 +18,11 @@ & \sum_{y\in \mathcal{DF}}{(-\Theta_{y,z,t}+\Pi_{y,z,t})} +\sum_{y\in \mathcal{W}}{\Theta_{y,z,t}}+ \notag\\ &+ \sum_{s\in \mathcal{S}}{\Lambda_{s,z,t}} - \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \Phi_{l,t})} -\frac{1}{2} \sum_{l\in \mathcal{L}}{(\varphi^{map}_{l,z} \times \beta_{l,t}(\cdot))} = D_{z,t} \forall z\in \mathcal{Z}, t \in \mathcal{T} -\end{aligned}\]

Arguments

  • setup::Dict: Dictionary containing the settings for the model.
  • inputs::Dict: Dictionary containing the inputs for the model.
  • OPTIMIZER::MOI.OptimizerWithAttributes: The optimizer to use for solving the model.

Returns

  • Model: The model object containing the entire optimization problem model to be solved by solve_model.jl
source
GenX.solve_modelFunction
solve_model(EP::Model, setup::Dict)

Description: Solves and extracts solution variables for later processing

Arguments

  • EP::Model: a JuMP model representing the energy optimization problem
  • setup::Dict: a Dict containing GenX setup flags

Returns

  • EP::Model: the solved JuMP model
  • solver_time::Float64: time taken to solve the model
source
GenX.write_outputsFunction
write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

Function for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.

source
GenX.mgaFunction
mga(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

We have implemented an updated Modeling to Generate Alternatives (MGA) Algorithm proposed by Berntsen and Trutnevyte (2017) to generate a set of feasible, near cost-optimal technology portfolios. This algorithm was developed by Brill Jr, E. D., 1979 and introduced to energy system planning by DeCarolia, J. F., 2011.

To create the MGA formulation, we replace the cost-minimizing objective function of GenX with a new objective function that creates multiple generation portfolios by zone. We further add a new budget constraint based on the optimal objective function value $f^*$ of the least-cost model and the user-specified value of slack $\delta$. After adding the slack constraint, the resulting MGA formulation is given as:

\[\begin{aligned} +\end{aligned}\]

Arguments

  • setup::Dict: Dictionary containing the settings for the model.
  • inputs::Dict: Dictionary containing the inputs for the model.
  • OPTIMIZER::MOI.OptimizerWithAttributes: The optimizer to use for solving the model.

Returns

  • Model: The model object containing the entire optimization problem model to be solved by solve_model.jl
source
GenX.solve_modelFunction
solve_model(EP::Model, setup::Dict)

Description: Solves and extracts solution variables for later processing

Arguments

  • EP::Model: a JuMP model representing the energy optimization problem
  • setup::Dict: a Dict containing GenX setup flags

Returns

  • EP::Model: the solved JuMP model
  • solver_time::Float64: time taken to solve the model
source
GenX.write_outputsFunction
write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

Function for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.

source
GenX.mgaFunction
mga(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)

We have implemented an updated Modeling to Generate Alternatives (MGA) Algorithm proposed by Berntsen and Trutnevyte (2017) to generate a set of feasible, near cost-optimal technology portfolios. This algorithm was developed by Brill Jr, E. D., 1979 and introduced to energy system planning by DeCarolia, J. F., 2011.

To create the MGA formulation, we replace the cost-minimizing objective function of GenX with a new objective function that creates multiple generation portfolios by zone. We further add a new budget constraint based on the optimal objective function value $f^*$ of the least-cost model and the user-specified value of slack $\delta$. After adding the slack constraint, the resulting MGA formulation is given as:

\[\begin{aligned} \text{max/min} \quad &\sum_{z \in \mathcal{Z}}\sum_{r \in \mathcal{R}} \beta_{z,r}^{k}P_{z,r}\\ \text{s.t.} \quad &P_{zr} = \sum_{y \in \mathcal{G}}\sum_{t \in \mathcal{T}} \omega_{t} \Theta_{y,t,z,r} \\ & f \leq f^* + \delta \\ &Ax = b -\end{aligned}\]

where, $\beta_{zr}$ is a random objective fucntion coefficient betwen $[0,100]$ for MGA iteration $k$. $\Theta_{y,t,z,r}$ is a generation of technology $y$ in zone $z$ in time period $t$ that belongs to a resource type $r$. We aggregate $\Theta_{y,t,z,r}$ into a new variable $P_{z,r}$ that represents total generation from technology type $r$ in a zone $z$. In the second constraint above, $\delta$ denote the increase in budget from the least-cost solution and $f$ represents the expression for the total system cost. The constraint $Ax = b$ represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.

source

Multi-stage specific functions

GenX.configure_multi_stage_inputsFunction
function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)

This function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:

  1. Overnight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.

  2. Annualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by "StageLength" field in multi_stage_settings.yml).

  3. Internal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.

  4. When NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the "Line_Max_Flow_Possible_MW" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.

inputs:

  • inputs_d - dict object containing model inputs dictionary generated by load_inputs().
  • settings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • NetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the "NetworkExpansion" field in genx_settings.yml.

returns: dictionary containing updated model inputs, to be used in the generate_model() method.

source
GenX.run_ddpFunction
run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)

This function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.

inputs:

  • models_d – Dictionary which contains a JuMP model for each model period.
  • setup - Dictionary object containing GenX settings and key parameters.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.

returns:

  • models_d – Dictionary which contains a JuMP model for each model stage, modified by this method.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.
source
GenX.write_multi_stage_outputsFunction
write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)

This function calls various methods which write multi-stage modeling outputs as .csv files.

inputs:

  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.
source
+\end{aligned}\]

where, $\beta_{zr}$ is a random objective fucntion coefficient betwen $[0,100]$ for MGA iteration $k$. $\Theta_{y,t,z,r}$ is a generation of technology $y$ in zone $z$ in time period $t$ that belongs to a resource type $r$. We aggregate $\Theta_{y,t,z,r}$ into a new variable $P_{z,r}$ that represents total generation from technology type $r$ in a zone $z$. In the second constraint above, $\delta$ denote the increase in budget from the least-cost solution and $f$ represents the expression for the total system cost. The constraint $Ax = b$ represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.

source

Multi-stage specific functions

GenX.configure_multi_stage_inputsFunction
function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)

This function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:

  1. Overnight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.

  2. Annualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by "StageLength" field in multi_stage_settings.yml).

  3. Internal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.

  4. When NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the "Line_Max_Flow_Possible_MW" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.

inputs:

  • inputs_d - dict object containing model inputs dictionary generated by load_inputs().
  • settings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.
  • NetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the "NetworkExpansion" field in genx_settings.yml.

returns: dictionary containing updated model inputs, to be used in the generate_model() method.

source
GenX.run_ddpFunction
run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)

This function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.

inputs:

  • models_d – Dictionary which contains a JuMP model for each model period.
  • setup - Dictionary object containing GenX settings and key parameters.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.

returns:

  • models_d – Dictionary which contains a JuMP model for each model stage, modified by this method.
  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • inputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.
source
GenX.write_multi_stage_outputsFunction
write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)

This function calls various methods which write multi-stage modeling outputs as .csv files.

inputs:

  • stats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.
  • outpath – String which represents the path to the Results directory.
  • settings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.
source
diff --git a/previews/PR655/Tutorials/Tutorial_1_configuring_settings/index.html b/previews/PR655/Tutorials/Tutorial_1_configuring_settings/index.html index 98434ef63a..db7cf6bdeb 100644 --- a/previews/PR655/Tutorials/Tutorial_1_configuring_settings/index.html +++ b/previews/PR655/Tutorials/Tutorial_1_configuring_settings/index.html @@ -265,4 +265,4 @@ Time elapsed for writing is 8.276978416

The function Run.jl will build and then solve the model according to the specified parameters. These results will then be output into a results folder in the same directory. Note that the results folders are not overwritten with each run.

using CSV
 using DataFrames
-results = CSV.read(open("example_systems/1_three_zones/Results/capacity.csv"),DataFrame)
11×15 DataFrame
RowResourceZoneStartCapRetCapNewCapEndCapCapacityConstraintDualStartEnergyCapRetEnergyCapNewEnergyCapEndEnergyCapStartChargeCapRetChargeCapNewChargeCapEndChargeCap
String31String3Float64Float64Float64Float64String3Float64Float64Float64Float64Float64Float64Float64Float64
1MA_natural_gas_combined_cycle10.00.07394.757394.750.00.00.00.00.00.00.00.00.0
2CT_natural_gas_combined_cycle20.00.02305.822305.820.00.00.00.00.00.00.00.00.0
3ME_natural_gas_combined_cycle30.00.0716.666716.6660.00.00.00.00.00.00.00.00.0
4MA_solar_pv10.00.021186.521186.50.00.00.00.00.00.00.00.00.0
5CT_onshore_wind20.00.011905.511905.50.00.00.00.00.00.00.00.00.0
6CT_solar_pv20.00.016578.816578.80.00.00.00.00.00.00.00.00.0
7ME_onshore_wind30.00.012767.312767.30.00.00.00.00.00.00.00.00.0
8MA_battery10.00.03362.33362.30.00.00.019427.719427.70.00.00.00.0
9CT_battery20.00.05318.365318.360.00.00.027274.127274.10.00.00.00.0
10ME_battery30.00.02095.32095.30.00.00.07096.277096.270.00.00.00.0
11Totaln/a0.00.083631.383631.3n/a0.00.053798.153798.10.00.00.00.0

As you can see, this runs without a problem! To try with your own parameters, edit the new_params dictionary with whatever parameters you'd like to try and run the cells again.Note: to output the results, you'll have to either delete the previous results folder, or input the name of the new results folder (e.g. results_1) when calling CSV.read as above.

Finally, let's rewite genx_settings.yml to put the original settings in the example back:

YAML.write_file("example_systems/1_three_zones/settings/genx_settings.yml", genx_settings_TZ)
+results = CSV.read(open("example_systems/1_three_zones/Results/capacity.csv"),DataFrame)
11×15 DataFrame
RowResourceZoneStartCapRetCapNewCapEndCapCapacityConstraintDualStartEnergyCapRetEnergyCapNewEnergyCapEndEnergyCapStartChargeCapRetChargeCapNewChargeCapEndChargeCap
String31String3Float64Float64Float64Float64String3Float64Float64Float64Float64Float64Float64Float64Float64
1MA_natural_gas_combined_cycle10.00.07394.757394.750.00.00.00.00.00.00.00.00.0
2CT_natural_gas_combined_cycle20.00.02305.822305.820.00.00.00.00.00.00.00.00.0
3ME_natural_gas_combined_cycle30.00.0716.666716.6660.00.00.00.00.00.00.00.00.0
4MA_solar_pv10.00.021186.521186.50.00.00.00.00.00.00.00.00.0
5CT_onshore_wind20.00.011905.511905.50.00.00.00.00.00.00.00.00.0
6CT_solar_pv20.00.016578.816578.80.00.00.00.00.00.00.00.00.0
7ME_onshore_wind30.00.012767.312767.30.00.00.00.00.00.00.00.00.0
8MA_battery10.00.03362.33362.30.00.00.019427.719427.70.00.00.00.0
9CT_battery20.00.05318.365318.360.00.00.027274.127274.10.00.00.00.0
10ME_battery30.00.02095.32095.30.00.00.07096.277096.270.00.00.00.0
11Totaln/a0.00.083631.383631.3n/a0.00.053798.153798.10.00.00.00.0

As you can see, this runs without a problem! To try with your own parameters, edit the new_params dictionary with whatever parameters you'd like to try and run the cells again.Note: to output the results, you'll have to either delete the previous results folder, or input the name of the new results folder (e.g. results_1) when calling CSV.read as above.

Finally, let's rewite genx_settings.yml to put the original settings in the example back:

YAML.write_file("example_systems/1_three_zones/settings/genx_settings.yml", genx_settings_TZ)
diff --git a/previews/PR655/Tutorials/Tutorial_2_network_visualization/index.html b/previews/PR655/Tutorials/Tutorial_2_network_visualization/index.html index c962af4796..f9e553c85e 100644 --- a/previews/PR655/Tutorials/Tutorial_2_network_visualization/index.html +++ b/previews/PR655/Tutorials/Tutorial_2_network_visualization/index.html @@ -1,3 +1,3 @@ Tutorial 2: Network Visualization · GenX

Tutorial 2: Network Visualization

Interactive Notebook of the tutorial

To run GenX, there are five mandatory input files: Fuels_data.csv, Network.csv, Load_data.csv, Generators_variability.csv, and Generators_data.csv. Detailed descriptions of these files can be found in the GenX Inputs page of the documentation. This tutorial helps visualize the file Network.csv using the example system example_systems/1_three_zones.

using CSV
-using DataFrames

The input file Network.csv contains the nodes of your network, how they connect to each other, and some important features about them. Below is the network file for example_systems/1_three_zones:

network = CSV.read("example_systems/1_three_zones/system/Network.csv",DataFrame,missingstring="NA")
3×14 DataFrame
RowColumn1Network_zonesNetwork_LinesStart_ZoneEnd_ZoneLine_Max_Flow_MWtransmission_path_namedistance_mileLine_Loss_PercentageLine_Max_Reinforcement_MWLine_Reinforcement_Cost_per_MWyrDerateCapRes_1CapRes_1CapRes_Excl_1
String3String3String3String3String3String7String15String15String15String7String7String7String3Int64?
1MAz11122950MA_to_CT123.05840.0123058372950120600.9500
2CTz22132000MA_to_ME196.53850.0196538472000192610.9500
3MEz3missing

MA, CT, and ME are the abbreviations for states Massachusetts, Connecticut, and Maine. However, since the US region of New England contains other states as well, MA in this case is also used to refer to those states.

Columns Start_Zone and End_Zone specify the network of the three regions. In this case, there are only two network lines, specified in the Network_Lines columns. The Start_Zone column indicates that the first node, MA, is the source of both lines as both rows have value 1. Rows z1 and z2 have values of 2 and 3 in End_Zone, which means both nodes CT and ME recieve energy from node MA. This is also indicated in the column `transmissionpathname'.

Below is a visualization of the network:

+using DataFrames

The input file Network.csv contains the nodes of your network, how they connect to each other, and some important features about them. Below is the network file for example_systems/1_three_zones:

network = CSV.read("example_systems/1_three_zones/system/Network.csv",DataFrame,missingstring="NA")
3×14 DataFrame
RowColumn1Network_zonesNetwork_LinesStart_ZoneEnd_ZoneLine_Max_Flow_MWtransmission_path_namedistance_mileLine_Loss_PercentageLine_Max_Reinforcement_MWLine_Reinforcement_Cost_per_MWyrDerateCapRes_1CapRes_1CapRes_Excl_1
String3String3String3String3String3String7String15String15String15String7String7String7String3Int64?
1MAz11122950MA_to_CT123.05840.0123058372950120600.9500
2CTz22132000MA_to_ME196.53850.0196538472000192610.9500
3MEz3missing

MA, CT, and ME are the abbreviations for states Massachusetts, Connecticut, and Maine. However, since the US region of New England contains other states as well, MA in this case is also used to refer to those states.

Columns Start_Zone and End_Zone specify the network of the three regions. In this case, there are only two network lines, specified in the Network_Lines columns. The Start_Zone column indicates that the first node, MA, is the source of both lines as both rows have value 1. Rows z1 and z2 have values of 2 and 3 in End_Zone, which means both nodes CT and ME recieve energy from node MA. This is also indicated in the column `transmissionpathname'.

Below is a visualization of the network:

diff --git a/previews/PR655/Tutorials/Tutorial_3_K-means_time_domain_reduction/index.html b/previews/PR655/Tutorials/Tutorial_3_K-means_time_domain_reduction/index.html index a3f95da7fd..347e768a98 100644 --- a/previews/PR655/Tutorials/Tutorial_3_K-means_time_domain_reduction/index.html +++ b/previews/PR655/Tutorials/Tutorial_3_K-means_time_domain_reduction/index.html @@ -241,4 +241,4 @@ scatter!(twinx(),obj_val_plot[:,1],times,color=:red,markeralpha=.5,label=:"Time",legend=:topleft, yaxis=(label="Time")) ygrid!(:on, :dashdot, 0.1)

Here, we can see that while having very few representative periods produces an objective value that differs greatly from the orignal, once we reach around 12 representative periods the difference begins to taper out. Therefore, the original choice of 11 maximum periods in 1_three_zones decreases the run time of GenX significantly while while maintaining an objective value close to the original.

It's important to note, however, that the difference does not always taper out, and for some systems you'll find that the error in objective value continues to decrease as the number of representative periods increases. There also is no way to know apriori what number of periods works.

Finally, let's set TDR to have 8 and 11 min/max periods again, and delete the TDR Results folder.

time_domain_reduction_settings["MinPeriods"] = 8;
-time_domain_reduction_settings["MaxPeriods"] = 11;
time_domain_reduction_settings
rm(joinpath(case,"TDR_results", recursive=true))

julia rm(joinpath(case,"TDR_results"), recursive=true) YAML.write_file(joinpath(case,"settings/time_domain_reduction_settings.yml"), time_domain_reduction_settings) folders = cd(readdir,case) for folder in folders if length(folder) >= 7 && folder[1:7] == "results" rm("example_systems/1_three_zones/" * folder,recursive=true) end end

+time_domain_reduction_settings["MaxPeriods"] = 11;
time_domain_reduction_settings
rm(joinpath(case,"TDR_results", recursive=true))

julia rm(joinpath(case,"TDR_results"), recursive=true) YAML.write_file(joinpath(case,"settings/time_domain_reduction_settings.yml"), time_domain_reduction_settings) folders = cd(readdir,case) for folder in folders if length(folder) >= 7 && folder[1:7] == "results" rm("example_systems/1_three_zones/" * folder,recursive=true) end end

diff --git a/previews/PR655/Tutorials/Tutorial_4_model_generation/index.html b/previews/PR655/Tutorials/Tutorial_4_model_generation/index.html index 30bb25da43..772d7e268a 100644 --- a/previews/PR655/Tutorials/Tutorial_4_model_generation/index.html +++ b/previews/PR655/Tutorials/Tutorial_4_model_generation/index.html @@ -324,4 +324,4 @@ cPowerBalance[1845,1] : vP[2,1845] + vP[3,1845] + vP[4,1845] + vNSE[1,1845,1] - vCHARGE[4,1845] = 15.392 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.

+ 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/previews/PR655/Tutorials/Tutorial_5_solve_model/index.html b/previews/PR655/Tutorials/Tutorial_5_solve_model/index.html index 3be2b3f821..8c7e8d7c7b 100644 --- a/previews/PR655/Tutorials/Tutorial_5_solve_model/index.html +++ b/previews/PR655/Tutorials/Tutorial_5_solve_model/index.html @@ -166,4 +166,4 @@ LP iterations 0 (total) 0 (strong br.) 0 (separation) - 0 (heuristics)

In this case, the infeasibility was detected on the presovle since it's clear no solution would fit within all constraints. For information on how to debug an infeasible solution, see the JuMP documentaion. Some solvers, such as Gurobi, will compute what is causing the conflict, e.g. which constraints are infeasible with one another (HiGHS does not do this).

GenX version 0.4 has the feature ComputeConflict in settings. If the model does not work, try setting ComputeConflict = 1, and the conflicting constraints will be returned.

Tutorial 6 describes the solver settings, how to change them, and the effects of PreSolve, Crossover, and Feasibility Tolerance.

+ 0 (heuristics)

In this case, the infeasibility was detected on the presovle since it's clear no solution would fit within all constraints. For information on how to debug an infeasible solution, see the JuMP documentaion. Some solvers, such as Gurobi, will compute what is causing the conflict, e.g. which constraints are infeasible with one another (HiGHS does not do this).

GenX version 0.4 has the feature ComputeConflict in settings. If the model does not work, try setting ComputeConflict = 1, and the conflicting constraints will be returned.

Tutorial 6 describes the solver settings, how to change them, and the effects of PreSolve, Crossover, and Feasibility Tolerance.

diff --git a/previews/PR655/Tutorials/Tutorial_6_solver_settings/index.html b/previews/PR655/Tutorials/Tutorial_6_solver_settings/index.html index 8ff8fc2785..a1db934f3b 100644 --- a/previews/PR655/Tutorials/Tutorial_6_solver_settings/index.html +++ b/previews/PR655/Tutorials/Tutorial_6_solver_settings/index.html @@ -327,4 +327,4 @@ HiGHS run time : 140.44 LP solved for primal - 140.74829025 + 140.74829025 diff --git a/previews/PR655/Tutorials/Tutorials_intro/index.html b/previews/PR655/Tutorials/Tutorials_intro/index.html index f4e5338c9d..37ec21d97d 100644 --- a/previews/PR655/Tutorials/Tutorials_intro/index.html +++ b/previews/PR655/Tutorials/Tutorials_intro/index.html @@ -1,2 +1,2 @@ -Tutorials Overview · GenX
+Tutorials Overview · GenX
diff --git a/previews/PR655/User_Guide/TDR_input/index.html b/previews/PR655/User_Guide/TDR_input/index.html index 9b24d48d13..9c1ceff58b 100644 --- a/previews/PR655/User_Guide/TDR_input/index.html +++ b/previews/PR655/User_Guide/TDR_input/index.html @@ -1,2 +1,2 @@ -Time-domain Reduction Inputs · GenX

Time-domain reduction

Modeling grid operations for each hour of the year can be computationally expensive for models with many zones and resources. Rather than modeling and optimizing power grid operations at a high temporal resolution (e.g., hourly, over a full year) while evaluating new capacity investments, which can be computationally expensive for large-scale studies with several resources, it may be useful to consider a reduced temporal resolution to model annual grid operations. Time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. Such a time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. GenX allows the option of performing time-domain reduction on the user supplied time-series input data to produce a representative time series at the desired level of temporal resolution. The time-domain reduction method provided allows the user to automate these features while specifying the various parameters of the time-domain reduction 'clustering' algorithm to be used in formulating the resulting optimization model. The below table summarizes the list of parameters to be specified by the user to perform the time domain reduction implemented in GenX. These parameters are passed to GenX via the YAML file time_domain_reduction_settings.yml.

It's also possible for GenX perform clustering separately from the optimization task. Check out the Running a case with Time Domain Reduction section for more information.

Structure of the time_domain_reduction.yml file

KeyDescription
Timesteps_per_periodThe number of timesteps (e.g., hours) in each representative period (i.e. 168 for weeks, 24 for days, 72 for three-day periods, etc).
UseExtremePeriods1 = Include outliers (by performance or demand/resource extreme) as their own representative extreme periods. This setting automatically includes periods based on criteria outlined in the dictionary ExtremePeriods. Extreme periods can be selected based on following criteria applied to demand profiles or solar and wind capacity factors profiles, at either the zonal or system level. A) absolute (timestep with min/max value) statistic (minimum, maximum) and B) integral (period with min/max summed value) statistic (minimum, maximum). For example, the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select Demand, System, Absolute, and Max.
0 = Do not include extreme periods.
ExtremePeriodsIf UseExtremePeriods = 1, use this dictionary to select which types of extreme periods to use. Select by profile type (Demand, PV, or Wind), geography (Zone or System), grouping by timestep or by period (Absolute or Integral), and statistic (Maximum or Minimum).
ClusterMethodEither kmeans or kmedoids, the method used to cluster periods and determine each time step's representative period.
ScalingMethodEither N or S, the decision to normalize ([0,1]) or standardize (mean 0, variance 1) the input data prior to clustering.
MinPeriodsThe minimum number of representative periods used to represent the input data. If using UseExtremePeriods, this must be greater or equal to the number of selected extreme periods. If IterativelyAddPeriods is off, this will be the total number of representative periods.
MaxPeriodsThe maximum number of representative periods - both clustered and extreme - that may be used to represent the input data.
IterativelyAddPeriods1 = Add representative periods until the error threshold between input data and represented data is met or the maximum number of representative periods is reached.
0 = Use only the minimum number of representative periods. This minimum value includes the selected extreme periods if UseExtremePeriods is on.
ThresholdIterative period addition will end if the period farthest from its representative period (as measured using Euclidean distance) is within this percentage of the total possible error (for normalization) or 95% of the total possible error (± 2 σ for standardization). E.g., for a threshold of 0.01, each period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the maximum is reached).
IterateMethodEither ‘cluster' (Default) or ‘extreme', whether to increment the number of clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.
nRepsDefault = 200, the number of kmeans/kmedoids repetitions at the same setting.
DemandWeightDefault = 1, a multiplier on demand columns to optionally prioritize better fits for demand profiles over resource capacity factor or fuel price profiles.
WeightTotalDefault = 8760, the sum to which the relative weights of representative periods will be scaled.
ClusterFuelPricesEither 1 or 0, whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data.csv in the TimeDomainReductionFolder with reshaped fuel prices based on the number and size of the representative periods but will not use the fuel price time series for selection of representative periods.
+Time-domain Reduction Inputs · GenX

Time-domain reduction

Modeling grid operations for each hour of the year can be computationally expensive for models with many zones and resources. Rather than modeling and optimizing power grid operations at a high temporal resolution (e.g., hourly, over a full year) while evaluating new capacity investments, which can be computationally expensive for large-scale studies with several resources, it may be useful to consider a reduced temporal resolution to model annual grid operations. Time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. Such a time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. GenX allows the option of performing time-domain reduction on the user supplied time-series input data to produce a representative time series at the desired level of temporal resolution. The time-domain reduction method provided allows the user to automate these features while specifying the various parameters of the time-domain reduction 'clustering' algorithm to be used in formulating the resulting optimization model. The below table summarizes the list of parameters to be specified by the user to perform the time domain reduction implemented in GenX. These parameters are passed to GenX via the YAML file time_domain_reduction_settings.yml.

It's also possible for GenX perform clustering separately from the optimization task. Check out the Running a case with Time Domain Reduction section for more information.

Structure of the time_domain_reduction.yml file

KeyDescription
Timesteps_per_periodThe number of timesteps (e.g., hours) in each representative period (i.e. 168 for weeks, 24 for days, 72 for three-day periods, etc).
UseExtremePeriods1 = Include outliers (by performance or demand/resource extreme) as their own representative extreme periods. This setting automatically includes periods based on criteria outlined in the dictionary ExtremePeriods. Extreme periods can be selected based on following criteria applied to demand profiles or solar and wind capacity factors profiles, at either the zonal or system level. A) absolute (timestep with min/max value) statistic (minimum, maximum) and B) integral (period with min/max summed value) statistic (minimum, maximum). For example, the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select Demand, System, Absolute, and Max.
0 = Do not include extreme periods.
ExtremePeriodsIf UseExtremePeriods = 1, use this dictionary to select which types of extreme periods to use. Select by profile type (Demand, PV, or Wind), geography (Zone or System), grouping by timestep or by period (Absolute or Integral), and statistic (Maximum or Minimum).
ClusterMethodEither kmeans or kmedoids, the method used to cluster periods and determine each time step's representative period.
ScalingMethodEither N or S, the decision to normalize ([0,1]) or standardize (mean 0, variance 1) the input data prior to clustering.
MinPeriodsThe minimum number of representative periods used to represent the input data. If using UseExtremePeriods, this must be greater or equal to the number of selected extreme periods. If IterativelyAddPeriods is off, this will be the total number of representative periods.
MaxPeriodsThe maximum number of representative periods - both clustered and extreme - that may be used to represent the input data.
IterativelyAddPeriods1 = Add representative periods until the error threshold between input data and represented data is met or the maximum number of representative periods is reached.
0 = Use only the minimum number of representative periods. This minimum value includes the selected extreme periods if UseExtremePeriods is on.
ThresholdIterative period addition will end if the period farthest from its representative period (as measured using Euclidean distance) is within this percentage of the total possible error (for normalization) or 95% of the total possible error (± 2 σ for standardization). E.g., for a threshold of 0.01, each period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the maximum is reached).
IterateMethodEither ‘cluster' (Default) or ‘extreme', whether to increment the number of clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.
nRepsDefault = 200, the number of kmeans/kmedoids repetitions at the same setting.
DemandWeightDefault = 1, a multiplier on demand columns to optionally prioritize better fits for demand profiles over resource capacity factor or fuel price profiles.
WeightTotalDefault = 8760, the sum to which the relative weights of representative periods will be scaled.
ClusterFuelPricesEither 1 or 0, whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data.csv in the TimeDomainReductionFolder with reshaped fuel prices based on the number and size of the representative periods but will not use the fuel price time series for selection of representative periods.
diff --git a/previews/PR655/User_Guide/generate_alternatives/index.html b/previews/PR655/User_Guide/generate_alternatives/index.html index 135bf7c681..6ad61e9119 100644 --- a/previews/PR655/User_Guide/generate_alternatives/index.html +++ b/previews/PR655/User_Guide/generate_alternatives/index.html @@ -1,2 +1,2 @@ -MGA package · GenX

Running Modeling to Generate Alternatives with GenX

GenX includes a modeling to generate alternatives (MGA) package that can be used to automatically enumerate a diverse set of near cost-optimal solutions to electricity system planning problems. To use the MGA algorithm, user will need to perform the following tasks:

  1. Add a Resource_Type column in all the resource .csv files denoting the type of each technology.
  2. Add a MGA column in all the resource .csv files denoting the availability of the technology.
  3. Set the ModelingToGenerateAlternatives flag in the GenX_Settings.yml file to 1.
  4. Set the ModelingtoGenerateAlternativeSlack flag in the GenX_Settings.yml file to the desirable level of slack.
  5. Create a Rand_mga_objective_coefficients.csv file to provide random objective function coefficients for each MGA iteration.

For each iteration, number of rows in the Rand_mga_objective_coefficients.csv file represents the number of distinct technology types while number of columns represent the number of model zones.

Solve the model using Run.jl file.

Results from the MGA algorithm would be saved in MGAmax and MGAmin folders in the Example_Systems/ folder.

+MGA package · GenX

Running Modeling to Generate Alternatives with GenX

GenX includes a modeling to generate alternatives (MGA) package that can be used to automatically enumerate a diverse set of near cost-optimal solutions to electricity system planning problems. To use the MGA algorithm, user will need to perform the following tasks:

  1. Add a Resource_Type column in all the resource .csv files denoting the type of each technology.
  2. Add a MGA column in all the resource .csv files denoting the availability of the technology.
  3. Set the ModelingToGenerateAlternatives flag in the GenX_Settings.yml file to 1.
  4. Set the ModelingtoGenerateAlternativeSlack flag in the GenX_Settings.yml file to the desirable level of slack.
  5. Create a Rand_mga_objective_coefficients.csv file to provide random objective function coefficients for each MGA iteration.

For each iteration, number of rows in the Rand_mga_objective_coefficients.csv file represents the number of distinct technology types while number of columns represent the number of model zones.

Solve the model using Run.jl file.

Results from the MGA algorithm would be saved in MGAmax and MGAmin folders in the Example_Systems/ folder.

diff --git a/previews/PR655/User_Guide/methodofmorris_input/index.html b/previews/PR655/User_Guide/methodofmorris_input/index.html index 0ced05b6a5..87d0ad6bec 100644 --- a/previews/PR655/User_Guide/methodofmorris_input/index.html +++ b/previews/PR655/User_Guide/methodofmorris_input/index.html @@ -1,2 +1,2 @@ -Method of Morris Inputs · GenX

Method_of_morris_range.csv (Example)

This file contains the settings parameters required to run the Method of Morris algorithm in GenX.

Note

This file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.

Column NameDescription
ResourceThis column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.
ZoneInteger representing zone number where the resource is located.
Lower_boundPercentage lower deviation from the nominal value
Upper_boundPercentage upper deviation from the nominal value
ParameterColumn from the Generators_data.csv file containing uncertain parameters
GroupGroup the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined
p_stepsNumber of steps between upper and lower bound
total_num_trajectoryTotal number of trakectories through the design matrix
num_trajectorySelected number of trajectories throigh the design matrix
len_design_matLength of the design matrix
policyName of the policy

Notes:

  1. Upper and lower bounds are specified in terms of percentage deviation from the nominal value.
  2. Percentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lower_bound and Upper_bound must be identical.
  3. P_steps should at least be = 1%, i.e., Upper_bound – Lower_bound < p_steps
  4. P_steps for parameters in one group must be identical
  5. Total_num_trajectory should be around 3 to 4 times the total number of uncertain parameters
  6. num_trajectory should be approximately equal to the total number of uncertain parameters
  7. len_design_mat should be 1.5 to 2 times the total number of uncertain parameters
  8. Higher number of num_trajectory and len_design_mat would lead to higher accuracy
  9. Upper and lower bounds should be specified for all the resources included in the Generators_data.csv file. If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.
+Method of Morris Inputs · GenX

Method_of_morris_range.csv (Example)

This file contains the settings parameters required to run the Method of Morris algorithm in GenX.

Note

This file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.

Column NameDescription
ResourceThis column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.
ZoneInteger representing zone number where the resource is located.
Lower_boundPercentage lower deviation from the nominal value
Upper_boundPercentage upper deviation from the nominal value
ParameterColumn from the Generators_data.csv file containing uncertain parameters
GroupGroup the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined
p_stepsNumber of steps between upper and lower bound
total_num_trajectoryTotal number of trakectories through the design matrix
num_trajectorySelected number of trajectories throigh the design matrix
len_design_matLength of the design matrix
policyName of the policy

Notes:

  1. Upper and lower bounds are specified in terms of percentage deviation from the nominal value.
  2. Percentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lower_bound and Upper_bound must be identical.
  3. P_steps should at least be = 1%, i.e., Upper_bound – Lower_bound < p_steps
  4. P_steps for parameters in one group must be identical
  5. Total_num_trajectory should be around 3 to 4 times the total number of uncertain parameters
  6. num_trajectory should be approximately equal to the total number of uncertain parameters
  7. len_design_mat should be 1.5 to 2 times the total number of uncertain parameters
  8. Higher number of num_trajectory and len_design_mat would lead to higher accuracy
  9. Upper and lower bounds should be specified for all the resources included in the Generators_data.csv file. If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.
diff --git a/previews/PR655/User_Guide/model_configuration/index.html b/previews/PR655/User_Guide/model_configuration/index.html index a17ffe9525..9371651404 100644 --- a/previews/PR655/User_Guide/model_configuration/index.html +++ b/previews/PR655/User_Guide/model_configuration/index.html @@ -1,2 +1,2 @@ -Model Configuration · GenX

Model settings parameters

The first step in configuring a GenX model is to specify the model settings parameters. These parameters are specified in a genx_settings.yml file inside a settings folder which must be located in the current working directory. Settings include those related to model structure, solution strategy and outputs, policy constraints, and others. In particular:

  • Model structure related settings parameters affect the formulation of the model constraints and objective function.
  • Computational performance related parameters affect the accuracy of the solution.
  • Policy related parameters specify the policy type and policy goal.
  • Network related parameters specify settings related to transmission network expansion and losses.

Note that all settings parameters are case sensitive.

(Optional) The user can also select the output files that they want to export using the output_settings.yml file. This file containes a list of yes/no options for each output file, and should be located in the settings folder. By default, if output_settings.yml is not included, GenX will export all output files.

The following tables summarize the model settings parameters and their default/possible values.

ParameterDescription
UCommitSelect technical resolution of of modeling thermal generators.
0 = no unit commitment.
1 = unit commitment with integer clustering.
2 = unit commitment with linearized clustering.
OperationalReservesFlag for modeling operational reserves .
0 = No operational reserves considered.
1 = Consider regulation (primary) and spinning (secondary) reserves.
StorageLossesFlag to account for storage related losses.
0 = VRE and CO2 constraints DO NOT account for energy lost.
1 = constraints account for energy lost.
TimeDomainReduction1 = Use time domain reduced inputs available in the folder with the name defined by settings parameter TimeDomainReductionFolder. If such a folder does not exist or it is empty, time domain reduction will reduce the input data and save the results there.
0 = Use the data in the main case folder; do not perform clustering.
TimeDomainReductionFolderName of the folder insie the current working directory where time domain reduced input data is stored.
VirtualChargeDischargeCostHypothetical cost of charging and discharging storage resources (in /MWh).

2. Solution strategy

ParameterDescription
ParameterScaleFlag to turn on parameter scaling wherein demand, capacity and power variables defined in GW rather than MW. This flag aides in improving the computational performance of the model.
1 = Scaling is activated.
0 = Scaling is not activated.
MultiStageModel multiple planning stages
1 = Model multiple planning stages as specified in multi_stage_settings.yml
0 = Model single planning stage
ModelingToGenerateAlternativesModeling to Generate Alternative Algorithm. For details, see here
1 = Use the algorithm.
0 = Do not use the algorithm.
ModelingtoGenerateAlternativeSlackvalue used to define the maximum deviation from the least-cost solution as a part of Modeling to Generate Alternative Algorithm. Can take any real value between 0 and 1.
MethodofMorrisMethod of Morris algorithm
1 = Use the algorithm.
0 = Do not use the algorithm.
ParameterDescription
CO2CapFlag for specifying the type of CO2 emission limit constraint.
0 = no CO2 emission limit
1 = mass-based emission limit constraint
2 = demand + rate-based emission limit constraint
3 = generation + rate-based emission limit constraint
EnergyShareRequirementFlag for specifying regional renewable portfolio standard (RPS) and clean energy standard policy (CES) related constraints.
Default = 0 (No RPS or CES constraints).
1 = activate energy share requirement related constraints.
CapacityReserveMarginFlag for Capacity Reserve Margin constraints.
Default = 0 (No Capacity Reserve Margin constraints)
1 = activate Capacity Reserve Margin related constraints
MinCapReqMinimum technology carve out requirement constraints.
1 = if one or more minimum technology capacity constraints are specified
0 = otherwise
MaxCapReqMaximum system-wide technology capacity limit constraints.
1 = if one or more maximum technology capacity constraints are specified
0 = otherwise
ParameterDescription
NetworkExpansionFlag for activating or deactivating inter-regional transmission expansion.
1 = active
0 = modeling single zone or for multi-zone problems in which inter regional transmission expansion is not allowed.
Trans_Loss_SegmentsNumber of segments to use in piece-wise linear approximation of losses.
1: linear
>=2: piece-wise quadratic

5. Outputs

ParameterDescription
PrintModelFlag for printing the model equations as .lp file.
1 = including the model equation as an output
0 = the model equation won't be included as an output
WriteShadowPricesGet the optimal values of dual variables of various model related constraints, including to estimate electricity prices, stored value of energy and the marginal CO2 prices.
WriteOutputsFlag for writing the model outputs with hourly resolution or just the annual sum.
"full" = write the model outputs with hourly resolution.
"annual" = write only the annual sum of the model outputs.

The next step in configuring a GenX model is to specify the solver settings parameters using a [solver_name]_settings.yml file inside the settings folder. The solver settings parameters are solver specific and are described in the following section.

+Model Configuration · GenX

Model settings parameters

The first step in configuring a GenX model is to specify the model settings parameters. These parameters are specified in a genx_settings.yml file inside a settings folder which must be located in the current working directory. Settings include those related to model structure, solution strategy and outputs, policy constraints, and others. In particular:

  • Model structure related settings parameters affect the formulation of the model constraints and objective function.
  • Computational performance related parameters affect the accuracy of the solution.
  • Policy related parameters specify the policy type and policy goal.
  • Network related parameters specify settings related to transmission network expansion and losses.

Note that all settings parameters are case sensitive.

(Optional) The user can also select the output files that they want to export using the output_settings.yml file. This file containes a list of yes/no options for each output file, and should be located in the settings folder. By default, if output_settings.yml is not included, GenX will export all output files.

The following tables summarize the model settings parameters and their default/possible values.

ParameterDescription
UCommitSelect technical resolution of of modeling thermal generators.
0 = no unit commitment.
1 = unit commitment with integer clustering.
2 = unit commitment with linearized clustering.
OperationalReservesFlag for modeling operational reserves .
0 = No operational reserves considered.
1 = Consider regulation (primary) and spinning (secondary) reserves.
StorageLossesFlag to account for storage related losses.
0 = VRE and CO2 constraints DO NOT account for energy lost.
1 = constraints account for energy lost.
TimeDomainReduction1 = Use time domain reduced inputs available in the folder with the name defined by settings parameter TimeDomainReductionFolder. If such a folder does not exist or it is empty, time domain reduction will reduce the input data and save the results there.
0 = Use the data in the main case folder; do not perform clustering.
TimeDomainReductionFolderName of the folder insie the current working directory where time domain reduced input data is stored.
VirtualChargeDischargeCostHypothetical cost of charging and discharging storage resources (in /MWh).

2. Solution strategy

ParameterDescription
ParameterScaleFlag to turn on parameter scaling wherein demand, capacity and power variables defined in GW rather than MW. This flag aides in improving the computational performance of the model.
1 = Scaling is activated.
0 = Scaling is not activated.
MultiStageModel multiple planning stages
1 = Model multiple planning stages as specified in multi_stage_settings.yml
0 = Model single planning stage
ModelingToGenerateAlternativesModeling to Generate Alternative Algorithm. For details, see here
1 = Use the algorithm.
0 = Do not use the algorithm.
ModelingtoGenerateAlternativeSlackvalue used to define the maximum deviation from the least-cost solution as a part of Modeling to Generate Alternative Algorithm. Can take any real value between 0 and 1.
MethodofMorrisMethod of Morris algorithm
1 = Use the algorithm.
0 = Do not use the algorithm.
ParameterDescription
CO2CapFlag for specifying the type of CO2 emission limit constraint.
0 = no CO2 emission limit
1 = mass-based emission limit constraint
2 = demand + rate-based emission limit constraint
3 = generation + rate-based emission limit constraint
EnergyShareRequirementFlag for specifying regional renewable portfolio standard (RPS) and clean energy standard policy (CES) related constraints.
Default = 0 (No RPS or CES constraints).
1 = activate energy share requirement related constraints.
CapacityReserveMarginFlag for Capacity Reserve Margin constraints.
Default = 0 (No Capacity Reserve Margin constraints)
1 = activate Capacity Reserve Margin related constraints
MinCapReqMinimum technology carve out requirement constraints.
1 = if one or more minimum technology capacity constraints are specified
0 = otherwise
MaxCapReqMaximum system-wide technology capacity limit constraints.
1 = if one or more maximum technology capacity constraints are specified
0 = otherwise
ParameterDescription
NetworkExpansionFlag for activating or deactivating inter-regional transmission expansion.
1 = active
0 = modeling single zone or for multi-zone problems in which inter regional transmission expansion is not allowed.
Trans_Loss_SegmentsNumber of segments to use in piece-wise linear approximation of losses.
1: linear
>=2: piece-wise quadratic

5. Outputs

ParameterDescription
PrintModelFlag for printing the model equations as .lp file.
1 = including the model equation as an output
0 = the model equation won't be included as an output
WriteShadowPricesGet the optimal values of dual variables of various model related constraints, including to estimate electricity prices, stored value of energy and the marginal CO2 prices.
WriteOutputsFlag for writing the model outputs with hourly resolution or just the annual sum.
"full" = write the model outputs with hourly resolution.
"annual" = write only the annual sum of the model outputs.

The next step in configuring a GenX model is to specify the solver settings parameters using a [solver_name]_settings.yml file inside the settings folder. The solver settings parameters are solver specific and are described in the following section.

diff --git a/previews/PR655/User_Guide/model_input/index.html b/previews/PR655/User_Guide/model_input/index.html index 33c9e6ff90..56a37735ea 100644 --- a/previews/PR655/User_Guide/model_input/index.html +++ b/previews/PR655/User_Guide/model_input/index.html @@ -3,4 +3,4 @@ 1, 1, 2, 2, 1, 3,

The matrix interface requires N columns labeled z1, z2, z3 ... zN, and L rows, one for each network line (or interregional path), with a 1 in the column corresponding to the 'start' zone and a -1 in the column corresponding to the 'end' zone for each line. Here is the same network map implemented as a matrix:

Network_Lines, z1, z2, z3,
             1,  1, -1,  0,
-            2,  1,  0, -1,

Note that in either case, positive flows indicate flow from start to end zone; negative flows indicate flow from end to start zone.

1.3 Demand_data.csv (Load_data.csv)

This file includes parameters to characterize model temporal resolution to approximate annual grid operations, electricity demand for each time step for each zone, and cost of load shedding. Note that GenX is designed to model hourly time steps. With some care and effort, finer (e.g. 15 minute) or courser (e.g. 2 hour) time steps can be modeled so long as all time-related parameters are scaled appropriately (e.g. time period weights, heat rates, ramp rates and minimum up and down times for generators, variable costs, etc).

Table 4: Structure of the Demand_data.csv file

Column NameDescription
Mandatory Columns
VollValue of lost load (also referred to as non-served energy) in /MWh.
Demand_SegmentNumber of demand curtailment/unserved demand segments with different cost and capacity of curtailable demand for each segment. User-specified demand segments. Integer values starting with 1 in the first row. Additional segements added in subsequent rows.
Cost_of_Demand_Curtailment_per_MWCost of non-served energy/demand curtailment (for each segment), reported as a fraction of value of the lost load (non-served demand). If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length equal to the length of Demand_Segment.
Max_Demand_CurtailmentMaximum time-dependent demand curtailable in each segment, reported as % of the demand in each zone and each period. If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length given by length of Demand_segment.
Time_IndexIndex defining time step in the model.
Demand_MW_z*Demand profile of a zone z* in MW; if multiple zones, this parameter will be a matrix with columns equal to number of zones (each column named appropriate zone number appended to parameter) and rows equal to number of time periods of grid operations being modeled.
Rep_PeriodsNumber of representative periods (e.g. weeks, days) that are modeled to approximate annual grid operations. This is always a single entry. For a full-year model, this is 1.
Timesteps_per_Rep_PeriodNumber of timesteps per representative period (e.g. 168 if period is set as a week using hour-long time steps). This is always a single entry: all representative periods have the same length. For a full-year model, this entry is equal to the number of time steps.
Sub_WeightsNumber of annual time steps (e.g. hours) represented by each timestep in a representative period. The length of this column is equal to the number of representative periods. The sum of the elements should be equal to the total number of time steps in a model time horizon (e.g. 8760 hours if modeling 365 days or 8736 if modeling 52 weeks).

1.4 Resources input files

The resources folder contains the input files for each resource type. At the current version of GenX, the following resources are included in the model:

  1. thermal generators, specified in the Thermal.csv file,
  2. variable renewable energy resources (VRE), specified in the VRE.csv file,
  3. reservoir hydro resources, specified in the Hydro.csv file,
  4. storage resources, specified in the Storage.csv file,
  5. flexible demand resources, specified in the Flex_demand.csv file,
  6. must-run resources, specified in the Must_run.csv file,
  7. electrolyzers, specified in the Electrolyzer.csv file, and
  8. co-located VRE and storage resources, specified in the Vre_stor.csv file.

Each file contains cost and performance parameters for various generators and other resources included in the model formulation. The following table describes the mandatory columns in each of these files. Note that the column names are case insensitive.

Table 5a: Mandatory columns in all resource .csv file

Column NameDescription
ResourceThis column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.
ZoneInteger representing zone number where the resource is located.
Technology type flags
New_Build{0, 1}, Flag for resource (storage, generation) eligibility for capacity expansion.
New_Build = 1: eligible for capacity expansion.
New_Build = 0: not eligible for capacity expansion.
Can_Retire{0, 1}, Flag for resource (storage, generation) eligibility for retirement.
Can_Retire = 1: eligible for retirement.
Can_Retire = 0: not eligible for retirement.
Existing technology capacity
Existing_Cap_MWThe existing capacity of a power plant in MW. Note that for co-located VRE-STOR resources, this capacity represents the existing AC grid connection capacity in MW.
Capacity/Energy requirements
Max_Cap_MW-1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the maximum AC grid connection capacity in MW.
Min_Cap_MW-1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the minimum AC grid connection capacity in MW.
Cost parameters
Inv_Cost_per_MWyrAnnualized capacity investment cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this annualized capacity investment cost pertains to the grid connection.
Fixed_OM_Cost_per_MWyrFixed operations and maintenance cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this fixed operations and maintenance cost pertains to the grid connection.
Var_OM_Cost_per_MWhVariable operations and maintenance cost of a technology (/MWh). Note that for co-located VRE-STOR resources, these costs apply to the AC generation sent to the grid from the entire site.
Technical performance parameters
Heat_Rate_MMBTU_per_MWhHeat rate of a generator or MMBtu of fuel consumed per MWh of electricity generated for export (net of on-site consumption). The heat rate is the inverse of the efficiency: a lower heat rate is better. Should be consistent with fuel prices in terms of reporting on higher heating value (HHV) or lower heating value (LHV) basis.
FuelFuel needed for a generator. The names should match with the ones in the Fuels_data.csv.
Required for writing outputs
regionName of the model region
clusterNumber of the cluster when representing multiple clusters of a given technology in a given region.
Required if electrolyzer is included in the model
QualifiedHydrogenSupply{0,1}, Indicates that generator or storage resources is eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint)
Required for retrofitting
Can_Retrofit{0, 1}, Flag for resource (storage, generation) eligibility for retrofit.
Can_Retrofit = 1: eligible for retrofit.
Can_Retrofit = 0: not eligible for retrofit.
Retrofit{0, 1}, Flag for resource retrofit technologies (i.e., retrofit options, e.g. CCS retrofit for coal plants).
Retrofit = 1: is a retrofit technology.
Retrofit = 0: is not a retrofit technology.
Retrofit_IdUnique identifier to group retrofittable source technologies with retrofit options inside the same zone.
Retrofit_Efficiency[0,1], Efficiency of the retrofit technology.
Table 5b: Settings-specific columns in all resource .csv file

Column NameDescription
ModelingToGenerateAlternatives = 1
MGAEligibility of the technology for Modeling To Generate Alternative (MGA) run.
1 = Technology is available for the MGA run.
0 = Technology is unavailable for the MGA run (e.g. storage technologies).
Resource_TypeFor the MGA run, we categorize all the resources in a few resource types. We then find maximally different generation portfolio based on these resource types. For example, existing solar and new solar resources could be represented by a resource type names Solar. Categorization of resources into resource types is user dependent.
Maintenance data
MAINT[0,1], toggles scheduled maintenance formulation.
Maintenance_Duration(Positive integer, less than total length of simulation.) Duration of the maintenance period, in number of timesteps. Only used if MAINT=1.
Maintenance_Cycle_Length_YearsLength of scheduled maintenance cycle, in years. 1 is maintenance every year, 3 is every three years, etc. (Positive integer. Only used if MAINT=1.)
Maintenance_Begin_CadenceCadence of timesteps in which scheduled maintenance can begin. 1 means that a maintenance period can start in any timestep, 24 means it can start only in timesteps 1, 25, 49, etc. A larger number can decrease the simulation computational cost as it limits the optimizer's choices. (Positive integer, less than total length of simulation. Only used if MAINT=1.)
CO2-related parameters required if any resources have nonzero CO2CaptureFraction
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_TonCost associated with CCS disposal (/tCO2), including pipeline, injection and storage costs of CCS-equipped generators.
Table 6a: Additional columns in the Thermal.csv file
Column NameDescription
Model{1, 2}, Flag to indicate membership in set of thermal resources (e.g. nuclear, combined heat and power, natural gas combined cycle, coal power plant)
Model = 1: If the power plant relies on thermal energy input and subject unit commitment constraints/decisions if UCommit >= 1 (e.g. cycling decisions/costs/constraints).
Model = 2: If the power plant relies on thermal energy input and is subject to simplified economic dispatch constraints (ramping limits and minimum output level but no cycling decisions/costs/constraints).
Min_Power[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.
Ramp_Up_Percentage[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Ramp_Dn_Percentage[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
PiecewiseFuelUsage-related parameters
PWFU_Fuel_Usage_Zero_Load_MMBTU_per_hThe fuel usage (MMBTU/h) for the first PWFU segemnt (y-intercept) at zero load.
PWFU_Heat_Rate_MMBTU_per_MWh_*iThe slope of fuel usage function of the segment i.
PWFU_Load_Point_MW_*iThe end of segment i (MW).
Multi-fuel parameters
MULTI_FUELS{0, 1}, Flag to indicate membership in set of thermal resources that can burn multiple fuels at the same time (e.g., natural gas combined cycle cofiring with hydrogen, coal power plant cofiring with natural gas.
MULTI_FUELS = 0: Not part of set (default)
MULTI_FUELS = 1: Resources that can use fuel blending.
Num_FuelsNumber of fuels that a multi-fuel generator (MULTIFUELS = 1) can use at the same time. The length of ['Fuel1', 'Fuel2', ...] should be equal to 'Num\Fuels'. Each fuel will requires its corresponding heat rate, min cofire level, and max cofire level.
Fuel1Frist fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.
Fuel2Second fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.
Heat1_Rate_MMBTU_per_MWhHeat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel1.
Heat2_Rate_MMBTU_per_MWhHeat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel2.
Fuel1_Min_Cofire_LevelThe minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel1_Min_CofireLevel\StartThe minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Fuel1_Max_Cofire_LevelThe maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel1_Max_CofireLevel\StartThe maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Fuel2_Min_Cofire_LevelThe minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel2_Min_CofireLevel\StartThe minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Fuel2_Max_Cofire_LevelThe maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel2_Max_CofireLevel\StartThe maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Table 6b: Settings-specific columns in the Thermal.csv file

Column NameDescription
UCommit >= 1The following settings apply only to thermal plants with unit commitment constraints
Up_TimeMinimum amount of time a resource has to stay in the committed state.
Down_TimeMinimum amount of time a resource has to remain in the shutdown state.
Start_Cost_per_MWCost per MW of nameplate capacity to start a generator (/MW per start). Multiplied by the number of generation units (each with a pre-specified nameplate capacity) that is turned on.
Start_Fuel_MMBTU_per_MWStartup fuel use per MW of nameplate capacity of each generator (MMBtu/MW per start).
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 7a: Additional columns in the Vre.csv file

Column NameDescription
Num_VRE_binsNumber of resource availability profiles considered for each VRE resource per zone. This parameter is used to decide the number of capacity investment decision variables related to a single variable renewable energy technology in each zone.
Num_VRE_bins = 1: using a single resource availability profile per technology per zone. 1 capacity investment decision variable and 1 generator RID tracking technology power output (and in each zone).
Num_VRE_bins > 1: using multiple resource availability profiles per technology per zone. Num_VRE_bins capacity investment decision variables and 1 generator RID used to define technology power output at each time step (and in each zone). Example: Suppose we are modeling 3 bins of wind profiles for each zone. Then include 3 rows with wind resource names as Wind_1, Wind_2, and Wind_3 and a corresponding increasing sequence of RIDs. Set Num_VRE_bins for the generator with smallest RID, Wind_1, to be 3 and set Num_VRE_bins for the other rows corresponding to Wind_2 and Wind_3, to be zero. By setting Num_VRE_bins for Wind_2 and Wind_3, the model eliminates the power outputs variables for these generators. The power output from the technology across all bins is reported in the power output variable for the first generator. This allows for multiple bins without significantly increasing number of model variables (adding each bin only adds one new capacity variable and no operational variables). See documentation for curtailable_variable_renewable() for more.
Table 6b: Settings-specific columns in the Vre.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 7a: Additional columns in the Hydro.csv file

Column NameDescription
Min_Power[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.
Ramp_Up_Percentage[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Ramp_Dn_Percentage[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Hydro_Energy_to_Power_RatioThe rated number of hours of reservoir hydro storage at peak discharge power output. (hours).
LDS{0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.
LDS = 0: Not part of set (default)
LDS = 1: Long duration storage resources
Table 7b: Settings-specific columns in the Hydro.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 8a: Additional columns in the Storage.csv file

Column NameDescription
Model{0, 1, 2}, Flag to indicate membership in set of storage resources and designate which type of storage resource formulation to employ.
Model = 0: Not part of set (default)
Model = 1: Discharging power capacity and energy capacity are the investment decision variables; symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage).
Model = 2: Discharging, charging power capacity and energy capacity are investment variables; asymmetric charge and discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
LDS{0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.
LDS = 0: Not part of set (default)
LDS = 1: Long duration storage resources
Self_Disch[0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs.
Eff_Up[0,1], Efficiency of charging storage.
Eff_Down[0,1], Efficiency of discharging storage.
Min_DurationSpecifies the minimum ratio of installed energy to discharged power capacity that can be installed (hours).
Max_DurationSpecifies the maximum ratio of installed energy to discharged power capacity that can be installed (hours).
Existing technology capacity
Existing_Cap_MWhThe existing capacity of storage in MWh where Model = 1 or Model = 2.
Existing_Charge_Cap_MWThe existing charging capacity for resources where Model = 2.
Capacity/Energy requirements
Max_Cap_MWh-1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.
Max_Charge_Cap_MW-1 (default) – no limit on maximum charge capacity of the resource. If non-negative, represents maximum allowed charge capacity (in MW) of the resource with Model = 2.
Min_Cap_MWh-1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.
Min_Charge_Cap_MW-1 (default) – no limit on minimum charge capacity of the resource. If non-negative, represents minimum allowed charge capacity (in MW) of the resource with Model = 2.
Cost parameters
Inv_Cost_per_MWhyrAnnualized investment cost of the energy capacity for a storage technology (/MW/year), applicable to either Model = 1 or Model = 2.
Inv_Cost_Charge_per_MWyrAnnualized capacity investment cost for the charging portion of a storage technology with Model = 2 (/MW/year).
Fixed_OM_Cost_per_MWhyrFixed operations and maintenance cost of the energy component of a storage technology (/MWh/year).
Fixed_OM_Cost_Charge_per_MWyrFixed operations and maintenance cost of the charging component of a storage technology of type Model = 2.
Var_OM_Cost_per_MWhInVariable operations and maintenance cost of the charging aspect of a storage technology with Model = 2. Otherwise 0 (/MWh).
Table 8b: Settings-specific columns in the Storage.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 9: Additional columns in the Flex_demand.csv file

Column NameDescription
Max_Flexible_Demand_DelayMaximum number of hours that demand can be deferred or delayed (hours).
Max_Flexible_Demand_AdvanceMaximum number of hours that demand can be scheduled in advance of the original schedule (hours).
Flexible_Demand_Energy_Eff[0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand (hours). For example, one may need to pre-cool a building more than normal to advance demand.
Cost parameters
Var_OM_Cost_per_MWhInVariable operations and maintenance costs associated with flexible demand deferral. Otherwise 0 (/MWh).
Table 10: Additional columns in the Electrolyzer.csv file

Column NameDescription
HydrogenMWhPer_TonneElectrolyzer efficiency in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced (MWh/t)
ElectrolyzerMinktMinimum annual quantity of hydrogen that must be produced by electrolyzer in kilotonnes (kt)
HydrogenPricePer_TonnePrice (or value) of hydrogen per metric tonne (/t)
Min_Power[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.
Ramp_Up_Percentage[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Ramp_Dn_Percentage[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Note

Check Qualified_Hydrogen_Supply column in table 5a if electrolyzers are included in the model. This column is used to indicate which resources are eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint).

Each co-located VRE and storage resource can be easily configured to contain either a co-located VRE-storage resource, standalone VRE resource (either wind, solar PV, or both), or standalone storage resource.

Table 11a: Additional columns in the Vre_stor.csv file

Column NameDescription
Technology type flags
SOLAR{0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a solar PV component.
SOLAR = 0: Not part of set (default)
SOLAR = 1: If the co-located VRE-storage resource can produce solar PV energy.
WIND{0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a wind component.
WIND = 0: Not part of set (default)
WIND = 1: If the co-located VRE-storage resource can produce wind energy.
STORDCDISCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharge behind the meter and through the inverter (DC).
STORDCDISCHARGE = 0: Not part of set (default)
STORDCDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCDISCHARGE = 1, STORDCCHARGE = 1.
STORDCDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
STORDCCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge through the inverter (DC).
STORDCCHARGE = 0: Not part of set (default)
STORDCCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCCHARGE = 1, STORDCDISCHARGE = 1.
STORDCCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
STORACDISCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharges AC.
STORACDISCHARGE = 0: Not part of set (default)
STORACDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACDISCHARGE = 1, STORACCHARGE = 1.
STORACDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
STORACCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge AC.
STORACCHARGE = 0: Not part of set (default)
STORACCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACCHARGE = 1, STORACDISCHARGE = 1.
STORACCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
LDSVRESTOR{0, 1}, Flag to indicate the co-located VRE-storage resources eligible for long duration storage constraints with inter period linkage (e.g., reservoir hydro, hydrogen storage).
LDSVRESTOR = 0: Not part of set (default)
LDSVRESTOR = 1: Long duration storage resources
Existing technology capacity
Existing_Cap_MWThe existing AC grid connection capacity in MW.
Existing_Cap_MWhThe existing capacity of storage in MWh.
Existing_Cap_Inverter_MWThe existing capacity of co-located VRE-STOR resource's inverter in MW (AC).
Existing_Cap_Solar_MWThe existing capacity of co-located VRE-STOR resource's solar PV in MW (DC).
Existing_Cap_Wind_MWThe existing capacity of co-located VRE-STOR resource's wind in MW (AC).
Existing_Cap_Discharge_DC_MWThe existing discharge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_DISCHARGE = 2.
Existing_Cap_Charge_DC_MWThe existing charge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_CHARGE = 2.
Existing_Cap_Discharge_AC_MWThe existing discharge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_AC_DISCHARGE = 2.
Existing_Cap_Charge_AC_MWThe existing charge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_DC_CHARGE = 2.
Capacity/Energy requirements
Max_Cap_MW-1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed AC grid connection capacity in MW of the resource.
Max_Cap_MWh-1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity of storage in MWh.
Min_Cap_MW-1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed AC grid connection capacity in MW.
Min_Cap_MWh-1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity of storage in MWh.
Max_Cap_Inverter_MW-1 (default) – no limit on maximum inverter capacity of the resource. If non-negative, represents maximum allowed inverter capacity (in MW AC) of the resource.
Max_Cap_Solar_MW-1 (default) – no limit on maximum solar PV capacity of the resource. If non-negative, represents maximum allowed solar PV capacity (in MW DC) of the resource.
Max_Cap_Wind_MW-1 (default) – no limit on maximum wind capacity of the resource. If non-negative, represents maximum allowed wind capacity (in MW AC) of the resource.
Max_Cap_Discharge_DC_MW-1 (default) – no limit on maximum DC discharge capacity of the resource. If non-negative, represents maximum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.
Max_Cap_Charge_DC_MW-1 (default) – no limit on maximum DC charge capacity of the resource. If non-negative, represents maximum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.
Max_Cap_Discharge_AC_MW-1 (default) – no limit on maximum AC discharge capacity of the resource. If non-negative, represents maximum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.
Max_Cap_Charge_AC_MW-1 (default) – no limit on maximum AC charge capacity of the resource. If non-negative, represents maximum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.
Min_Cap_Inverter_MW-1 (default) – no limit on minimum inverter capacity of the resource. If non-negative, represents minimum allowed inverter capacity (in MW AC) of the resource.
Min_Cap_Solar_MW-1 (default) – no limit on minimum solar PV capacity of the resource. If non-negative, represents minimum allowed solar PV capacity (in MW DC) of the resource.
Min_Cap_Wind_MW-1 (default) – no limit on minimum wind capacity of the resource. If non-negative, represents minimum allowed wind capacity (in MW AC) of the resource.
Min_Cap_Discharge_DC_MW-1 (default) – no limit on minimum DC discharge capacity of the resource. If non-negative, represents minimum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.
Min_Cap_Charge_DC_MW-1 (default) – no limit on minimum DC charge capacity of the resource. If non-negative, represents minimum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.
Min_Cap_Discharge_AC_MW-1 (default) – no limit on minimum AC discharge capacity of the resource. If non-negative, represents minimum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.
Min_Cap_Charge_AC_MW-1 (default) – no limit on minimum AC charge capacity of the resource. If non-negative, represents minimum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.
Cost parameters
Inv_Cost_per_MWyrAnnualized capacity investment cost of the grid connection (/MW/year).
Inv_Cost_per_MWhyrAnnualized investment cost of the energy capacity for the co-located storage resource (/MW/year)
Fixed_OM_Cost_per_MWyrFixed operations and maintenance cost of the grid connection (/MW/year).
Fixed_OM_Cost_per_MWhyrFixed operations and maintenance cost of the energy component of the co-located storage resource. (/MWh/year).
Inv_Cost_Inverter_per_MWyrAnnualized capacity investment cost of the inverter component (/MW-AC/year).
Inv_Cost_Solar_per_MWyrAnnualized capacity investment cost of the solar PV component (/MW-DC/year).
Inv_Cost_Wind_per_MWyrAnnualized capacity investment cost of the wind component (/MW-AC/year).
Inv_Cost_Discharge_DC_per_MWyrAnnualized capacity investment cost for the discharging portion of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).
Inv_Cost_Charge_DC_per_MWyrAnnualized capacity investment cost for the charging portion of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).
Inv_Cost_Discharge_AC_per_MWyrAnnualized capacity investment cost for the discharging portion of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).
Inv_Cost_Charge_AC_per_MWyrAnnualized capacity investment cost for the charging portion of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).
Fixed_OM_Inverter_Cost_per_MWyrFixed operations and maintenance cost of the inverter component (/MW-AC/year).
Fixed_OM_Solar_Cost_per_MWyrFixed operations and maintenance cost of the solar PV component (/MW-DC/year).
Fixed_OM_Wind_Cost_per_MWyrFixed operations and maintenance cost of the wind component (/MW-AC/year).
Fixed_OM_Cost_Discharge_DC_per_MWyrFixed operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).
Fixed_OM_Cost_Charge_DC_per_MWyrFixed operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).
Fixed_OM_Cost_Discharge_AC_per_MWyrFixed operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).
Fixed_OM_Cost_Charge_AC_per_MWyrFixed operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).
Var_OM_Cost_per_MWh_SolarVariable operations and maintenance cost of the solar PV component (multiplied by the inverter efficiency for AC terms) (/MWh).
Var_OM_Cost_per_MWh_WindVariable operations and maintenance cost of the wind component (/MWh).
Var_OM_Cost_per_MWh_Discharge_DCVariable operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (multiplied by the inverter efficiency for AC terms) (/MWh).
Var_OM_Cost_per_MWh_Charge_DCVariable operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (divided by the inverter efficiency for AC terms) (/MWh).
Var_OM_Cost_per_MWh_Discharge_ACVariable operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MWh).
Var_OM_Cost_per_MWh_Charge_ACVariable operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MWh).
Technical performance parameters
Self_Disch[0,1], The power loss of storage component of each resource per hour (fraction loss per hour).
EtaInverter[0,1], Inverter efficiency representing losses from converting DC to AC power and vice versa for each technology
InverterRatioSolar-1 (default) - no required ratio between solar PV capacity built to inverter capacity built. If non-negative, represents the ratio of solar PV capacity built to inverter capacity built.
InverterRatioWind-1 (default) - no required ratio between wind capacity built to grid connection capacity built. If non-negative, represents the ratio of wind capacity built to grid connection capacity built.
Power_to_Energy_ACThe power to energy conversion for the storage component for AC discharging/charging of symmetric storage resources.
Power_to_Energy_DCThe power to energy conversion for the storage component for DC discharging/charging of symmetric storage resources.
Eff_Up_DC[0,1], Efficiency of DC charging storage – applies to storage technologies (all STOR types).
Eff_Down_DC[0,1], Efficiency of DC discharging storage – applies to storage technologies (all STOR types).
Eff_Up_AC[0,1], Efficiency of AC charging storage – applies to storage technologies (all STOR types).
Eff_Down_AC[0,1], Efficiency of AC discharging storage – applies to storage technologies (all STOR types).
Table 11b: Settings-specific columns in the Vre_stor.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.

In addition to the files described above, the resources folder contains the following files that are used to specify policy-related parameters for specific resources:

  1. Resource_energy_share_requirement.csv
  2. Resource_minimum_capacity_requirement.csv
  3. Resource_maximum_capacity_requirement.csv
  4. Resource_capacity_reserve_margin.csv
Note

These files are optional and can be omitted if no policy-related parameters are specified in the settings file. Also, not all the resources need to be included in these files, only those for which the policy applies.

The following table describes the columns in each of these four files.

Warning

The first column of each file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in the policy files is not important.

This policy is applied when if EnergyShareRequirement > 0 in the settings file. * corresponds to the ith row of the file Energy_share_requirement.csv.

Table 12: Energy share requirement policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
ESR_*Flag to indicate which resources are considered for the Energy Share Requirement constraint.
1- included
0- excluded
co-located VRE-STOR resources only
ESRVreStor_*Flag to indicate which resources are considered for the Energy Share Requirement constraint.
1- included
0- excluded

This policy is applied when if MinCapReq = 1 in the settings file. * corresponds to the ith row of the file Minimum_capacity_requirement.csv.

Table 13: Minimum capacity requirement policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
MinCap\*Flag to indicate which resources are considered for the Minimum Capacity Requirement constraint.
co-located VRE-STOR resources only
MinCapSolar_*Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Minimum Technology Carveout constraint.
MinCapWind_*Eligibility of resources with a wind component to participate in Minimum Technology Carveout constraint (AC terms).
MinCapStor_*Eligibility of resources with a storage component to participate in Minimum Technology Carveout constraint (discharge capacity in AC terms).

This policy is applied when if MaxCapReq = 1 in the settings file. * corresponds to the ith row of the file Maximum_capacity_requirement.csv.

Table 14: Maximum capacity requirement policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
MaxCap\*Flag to indicate which resources are considered for the Maximum Capacity Requirement constraint.
co-located VRE-STOR resources only
MaxCapSolar_*Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Maximum Technology Carveout constraint.
MaxCapWind_*Eligibility of resources with a wind component to participate in Maximum Technology Carveout constraint (AC terms).
MaxCapStor_*Eligibility of resources with a storage component to participate in Maximum Technology Carveout constraint (discharge capacity in AC terms).

This policy is applied when if CapacityReserveMargin > 0 in the settings file. * corresponds to the ith row of the file Capacity_reserve_margin.csv.

Table 15: Capacity reserve margin policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
EligibleCapRes_*Fraction of the resource capacity eligible for contributing to the capacity reserve margin constraint (e.g. derate factor).

In addition to the files described above, the resources folder can contain additional files that are used to specify attributes for specific resources and modules. Currently, the following files are supported:

  1. Resource_multistage_data.csv: mandatory if MultiStage = 1 in the settings file

<!– 2) Resource_piecewisefuel_usage.csv –>

Warning

The first column of each additional module file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in these files is not important.

Table 16: Multistage parameters
Warning

This file is mandatory if MultiStage = 1 in the settings file.


Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
Capital_Recovery_PeriodCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.
LifetimeLifetime (in years) used for determining endogenous retirements of newly built capacity. Note that the same lifetime is used for each component of a co-located VRE-STOR resource.
Min_Retired_Cap_MWMinimum required discharge capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.
Min_Retired_Energy_Cap_MWMinimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing energy capacity. Note that for co-located VRE-STOR resources, this value pertains to the storage component.
Min_Retired_Charge_Cap_MWMinimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing charge capacity.
Contribute_Min_Retirement{0, 1}, Flag to indicate whether the (retrofitting) resource can contribute to the minimum retirement requirement.
co-located VRE-STOR resources only
Capital_Recovery_Period_DCCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the inverter component.
Capital_Recovery_Period_SolarCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the solar PV component.
Capital_Recovery_Period_WindCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the wind component.
Capital_Recovery_PeriodDischargeDCCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge DC component when STOR_DC_DISCHARGE = 2.
Capital_Recovery_PeriodChargeDCCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge DC component when STOR_DC_CHARGE = 2.
Capital_Recovery_PeriodDischargeACCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge AC component when STOR_AC_DISCHARGE = 2.
Capital_Recovery_PeriodChargeACCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge AC component when STOR_AC_CHARGE = 2.
Min_Retired_Cap_Inverter_MWMinimum required inverter capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_Solar_MWMinimum required solar capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_Wind_MWMinimum required wind capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_DischargeDC\MWMinimum required discharge capacity retirements in the current model period for storage resources with STOR_DC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_ChargeDC\MWMinimum required charge capacity retirements in the current model period for storage resources with STOR_DC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_DischargeAC\MWMinimum required discharge capacity retirements in the current model period for storage resources with STOR_AC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_ChargeAC\MWMinimum required charge capacity retirements in the current model period for storage resources with STOR_AC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
WACC_DCThe line-specific weighted average cost of capital for the inverter component.
WACC_SolarThe line-specific weighted average cost of capital for the solar PV component.
WACC_WindThe line-specific weighted average cost of capital for the wind component.
WACC_Discharge_DCThe line-specific weighted average cost of capital for the discharging DC storage component with STOR_DC_DISCHARGE = 2.
WACC_Charge_DCThe line-specific weighted average cost of capital for the charging DC storage component with STOR_DC_CHARGE = 2.
WACC_Discharge_ACThe line-specific weighted average cost of capital for the discharging AC storage component with STOR_AC_DISCHARGE = 2.
WACC_Charge_ACThe line-specific weighted average cost of capital for the charging AC storage component with STOR_AC_CHARGE = 2.

1.5 Generator_variability.csv

This file contains the time-series of capacity factors / availability of each resource included in the resource .csv file in the resources folder for each time step (e.g. hour) modeled.

• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.

• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the resource .csv file in the resources folder in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in the resource .csv file must be unique. Note that for Hydro reservoir resources (i.e. Hydro.csv), values in this file correspond to inflows (in MWhs) to the hydro reservoir as a fraction of installed power capacity, rather than hourly capacity factor. Note that for co-located VRE and storage resources, solar PV and wind resource profiles should not be located in this file but rather in separate variability files (these variabilities can be in the Generators_variability.csv if time domain reduction functionalities will be utilized because the time domain reduction functionalities will separate the files after the clustering is completed).

|Self_Disch |[0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs. Note that for co-located VRE-STOR resources, this value applies to the storage component of each resource.| |Min_Power |[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Up_Percentage |[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Dn_Percentage |[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Eff_Up |[0,1], Efficiency of charging storage – applies to storage technologies (all STOR types except co-located storage resources).| |Eff_Down |[0,1], Efficiency of discharging storage – applies to storage technologies (all STOR types except co-located storage resources). |

|Min_Duration |Specifies the minimum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Duration |Specifies the maximum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Flexible_Demand_Delay |Maximum number of hours that demand can be deferred or delayed. Applies to resources with FLEX type 1 (hours). | |Max_Flexible_Demand_Advance |Maximum number of hours that demand can be scheduled in advance of the original schedule. Applies to resources with FLEX type 1 (hours). | |Flexible_Demand_Energy_Eff |[0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand. Applies to resources with FLEX type 1 (hours). For example, one may need to pre-cool a building more than normal to advance demand. |

1.6 Vre_and_stor_solar_variability.csv

This file contains the time-series of capacity factors / availability of the solar PV component (DC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.

• first column: The first column contains the time index of each row (starting in the second row) from 1 to N.

• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique.

1.7 Vre_and_stor_wind_variability.csv

This file contains the time-series of capacity factors / availability of the wind component (AC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.

• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.

• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique.

2. Optional inputs files

2.1 Operational_reserves.csv

This file includes parameter inputs needed to model time-dependent procurement of regulation and spinning reserves. This file is needed if OperationalReserves flag is activated in the YAML file genx_settings.yml.

Table 7: Structure of the Operational_reserves.csv file

Column NameDescription
Reg_Req_Percent_Demand[0,1], Regulation requirement as a percent of time-dependent demand; here demand is the total across all model zones.
Reg_Req_Percent_VRE[0,1], Regulation requirement as a percent of time-dependent wind and solar generation (summed across all model zones).
Rsv_Req_Percent_Demand [0,1],Spinning up or contingency reserve requirement as a percent of time-dependent demand (which is summed across all zones).
Rsv_Req_Percent_VRE[0,1], Spinning up or contingency reserve requirement as a percent of time-dependent wind and solar generation (which is summed across all zones).
Unmet_Rsv_Penalty_Dollar_per_MWPenalty for not meeting time-dependent spinning reserve requirement (/MW per time step).
Dynamic_ContingencyFlags to include capacity (generation or transmission) contingency to be added to the spinning reserve requirement.
Dynamic_Contingency= 1: contingency set to be equal to largest installed thermal unit (only applied when UCommit = 1).
= 2: contingency set to be equal to largest committed thermal unit each time period (only applied when UCommit = 1).
Static_Contingency_MWA fixed static contingency in MW added to reserve requirement. Applied when UCommit = 1 and DynamicContingency = 0, or when UCommit = 2. Contingency term not included in operating reserve requirement when this value is set to 0 and DynamicContingency is not active.

2.2 Energy_share_requirement.csv

This file contains inputs specifying minimum energy share requirement policies, such as Renewable Portfolio Standard (RPS) or Clean Energy Standard (CES) policies. This file is needed if parameter EnergyShareRequirement has a non-zero value in the YAML file genx_settings.yml.

Note: this file should use the same region name as specified in the the resource .csv file (inside the Resource).

Table 8: Structure of the Energy_share_requirement.csv file

Column NameDescription
Region_descriptionRegion name
Network_zoneszone number represented as z*
ESR_*[0,1], Energy share requirements as a share of zonal demand (calculated on an annual basis). * represents the number of the ESR constraint, given by the number of ESR_* columns in the Energy_share_requirement.csv file.

2.3 CO2_cap.csv

This file contains inputs specifying CO2 emission limits policies (e.g. emissions cap and permit trading programs). This file is needed if CO2Cap flag is activated in the YAML file genx_settings.yml. CO2Cap flag set to 1 represents mass-based (tCO2 ) emission target. CO2Cap flag set to 2 is specified when emission target is given in terms of rate (tCO2/MWh) and is based on total demand met. CO2Cap flag set to 3 is specified when emission target is given in terms of rate (tCO2 /MWh) and is based on total generation.

Table 9: Structure of the CO2_cap.csv file

Column NameDescription
Region_descriptionRegion name
Network_zoneszone number represented as z*
CO_2_Cap_Zone_*If a zone is eligible for the emission limit constraint, then this column is set to 1, else 0.
CO_2_Max_tons_MWh_*Emission limit in terms of rate
CO_2_Max_Mtons_*Emission limit in absolute values, in Million of tons
where in the above inputs, * represents the number of the emission limit constraints. For example, if the model has 2 emission limit constraints applied separately for 2 zones, the above CSV file will have 2 columns for specifying emission limit in terms on rate: CO_2_Max_tons_MWh_1 and CO_2_Max_tons_MWh_2.

2.4 Capacity_reserve_margin.csv

This file contains the regional capacity reserve margin requirements. This file is needed if parameter CapacityReserveMargin has a non-zero value in the YAML file genx_settings.yml.

Note: this file should use the same region name as specified in the resource .csv file (inside the Resource).

Table 10: Structure of the Capacity_reserve_margin.csv file

Column NameDescription
Region_descriptionRegion name
Network_zoneszone number represented as z*
CapRes_*[0,1], Capacity reserve margin requirements of a zone, reported as a fraction of demand

2.5 Minimum_capacity_requirement.csv

This file contains the minimum capacity carve-out requirement to be imposed (e.g. a storage capacity mandate or offshore wind capacity mandate). This file is needed if the MinCapReq flag has a non-zero value in the YAML file genx_settings.yml.

Table 11: Structure of the Minimum_capacity_requirement.csv file

Column NameDescription
MinCapReqConstraintIndex of the minimum capacity carve-out requirement.
Constraint_DescriptionNames of minimum capacity carve-out constraints; not to be read by model, but used as a helpful notation to the model user.
Min_MWminimum capacity requirement [MW]

Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.

2.6 Maximum_capacity_requirement.csv

This contains the maximum capacity limits to be imposed (e.g. limits on total deployment of solar, wind, or batteries in the system as a whole or in certain collections of zones). It is required if the MaxCapReq flag has a non-zero value in genx_settings.yml.

Table 12: Structure of the Maximum_capacity_requirement.csv file

Column NameDescription
MaxCapReqConstraintIndex of the maximum capacity limit.
Constraint_DescriptionNames of maximum capacity limit; not to be read by model, but used as a helpful notation to the model user.
Max_MWmaximum capacity limit [MW]

Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.

2.7 Method_of_morris_range.csv

This file contains the settings parameters required to run the Method of Morris algorithm in GenX. This file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.

Table 13: Structure of the Method_of_morris_range.csv file

Column NameDescription
ResourceThis column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand/loads.
ZoneInteger representing zone number where the resource is located.
Lower_boundPercentage lower deviation from the nominal value
Upper_boundPercentage upper deviation from the nominal value
ParameterColumn from the resource .csv file (inside the Resource) containing uncertain parameters
GroupGroup the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined
p_stepsNumber of steps between upper and lower bound
total_num_trajectoryTotal number of trakectories through the design matrix
num_trajectorySelected number of trajectories throigh the design matrix
len_design_matLength of the design matrix
policyName of the policy
Notes
  1. Upper and lower bounds are specified in terms of percentage deviation from the nominal value.
  2. Percentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lowerbound and Upperbound must be identical
  3. P_steps should at least be = 1\%, i.e., Upper_bound – Lower_bound $<$ p_steps
  4. P_steps for parameters in one group must be identical
  5. Total_num_trajectory should be around 3 to 4 times the total number of uncertain parameters
  6. num_trajectory should be approximately equal to the total number of uncertain parameters
  7. len_design_mat should be 1.5 to 2 times the total number of uncertain parameters
  8. Higher number of num_trajectory and lendesignmat would lead to higher accuracy
  9. Upper and lower bounds should be specified for all the resources included in the resource .csv file (inside the Resource). If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.
+ 2, 1, 0, -1,

Note that in either case, positive flows indicate flow from start to end zone; negative flows indicate flow from end to start zone.

1.3 Demand_data.csv (Load_data.csv)

This file includes parameters to characterize model temporal resolution to approximate annual grid operations, electricity demand for each time step for each zone, and cost of load shedding. Note that GenX is designed to model hourly time steps. With some care and effort, finer (e.g. 15 minute) or courser (e.g. 2 hour) time steps can be modeled so long as all time-related parameters are scaled appropriately (e.g. time period weights, heat rates, ramp rates and minimum up and down times for generators, variable costs, etc).

Table 4: Structure of the Demand_data.csv file

Column NameDescription
Mandatory Columns
VollValue of lost load (also referred to as non-served energy) in /MWh.
Demand_SegmentNumber of demand curtailment/unserved demand segments with different cost and capacity of curtailable demand for each segment. User-specified demand segments. Integer values starting with 1 in the first row. Additional segements added in subsequent rows.
Cost_of_Demand_Curtailment_per_MWCost of non-served energy/demand curtailment (for each segment), reported as a fraction of value of the lost load (non-served demand). If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length equal to the length of Demand_Segment.
Max_Demand_CurtailmentMaximum time-dependent demand curtailable in each segment, reported as % of the demand in each zone and each period. If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length given by length of Demand_segment.
Time_IndexIndex defining time step in the model.
Demand_MW_z*Demand profile of a zone z* in MW; if multiple zones, this parameter will be a matrix with columns equal to number of zones (each column named appropriate zone number appended to parameter) and rows equal to number of time periods of grid operations being modeled.
Rep_PeriodsNumber of representative periods (e.g. weeks, days) that are modeled to approximate annual grid operations. This is always a single entry. For a full-year model, this is 1.
Timesteps_per_Rep_PeriodNumber of timesteps per representative period (e.g. 168 if period is set as a week using hour-long time steps). This is always a single entry: all representative periods have the same length. For a full-year model, this entry is equal to the number of time steps.
Sub_WeightsNumber of annual time steps (e.g. hours) represented by each timestep in a representative period. The length of this column is equal to the number of representative periods. The sum of the elements should be equal to the total number of time steps in a model time horizon (e.g. 8760 hours if modeling 365 days or 8736 if modeling 52 weeks).

1.4 Resources input files

The resources folder contains the input files for each resource type. At the current version of GenX, the following resources are included in the model:

  1. thermal generators, specified in the Thermal.csv file,
  2. variable renewable energy resources (VRE), specified in the VRE.csv file,
  3. reservoir hydro resources, specified in the Hydro.csv file,
  4. storage resources, specified in the Storage.csv file,
  5. flexible demand resources, specified in the Flex_demand.csv file,
  6. must-run resources, specified in the Must_run.csv file,
  7. electrolyzers, specified in the Electrolyzer.csv file, and
  8. co-located VRE and storage resources, specified in the Vre_stor.csv file.

Each file contains cost and performance parameters for various generators and other resources included in the model formulation. The following table describes the mandatory columns in each of these files. Note that the column names are case insensitive.

Table 5a: Mandatory columns in all resource .csv file

Column NameDescription
ResourceThis column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.
ZoneInteger representing zone number where the resource is located.
Technology type flags
New_Build{0, 1}, Flag for resource (storage, generation) eligibility for capacity expansion.
New_Build = 1: eligible for capacity expansion.
New_Build = 0: not eligible for capacity expansion.
Can_Retire{0, 1}, Flag for resource (storage, generation) eligibility for retirement.
Can_Retire = 1: eligible for retirement.
Can_Retire = 0: not eligible for retirement.
Existing technology capacity
Existing_Cap_MWThe existing capacity of a power plant in MW. Note that for co-located VRE-STOR resources, this capacity represents the existing AC grid connection capacity in MW.
Capacity/Energy requirements
Max_Cap_MW-1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the maximum AC grid connection capacity in MW.
Min_Cap_MW-1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the minimum AC grid connection capacity in MW.
Cost parameters
Inv_Cost_per_MWyrAnnualized capacity investment cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this annualized capacity investment cost pertains to the grid connection.
Fixed_OM_Cost_per_MWyrFixed operations and maintenance cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this fixed operations and maintenance cost pertains to the grid connection.
Var_OM_Cost_per_MWhVariable operations and maintenance cost of a technology (/MWh). Note that for co-located VRE-STOR resources, these costs apply to the AC generation sent to the grid from the entire site.
Technical performance parameters
Heat_Rate_MMBTU_per_MWhHeat rate of a generator or MMBtu of fuel consumed per MWh of electricity generated for export (net of on-site consumption). The heat rate is the inverse of the efficiency: a lower heat rate is better. Should be consistent with fuel prices in terms of reporting on higher heating value (HHV) or lower heating value (LHV) basis.
FuelFuel needed for a generator. The names should match with the ones in the Fuels_data.csv.
Required for writing outputs
regionName of the model region
clusterNumber of the cluster when representing multiple clusters of a given technology in a given region.
Required if electrolyzer is included in the model
QualifiedHydrogenSupply{0,1}, Indicates that generator or storage resources is eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint)
Required for retrofitting
Can_Retrofit{0, 1}, Flag for resource (storage, generation) eligibility for retrofit.
Can_Retrofit = 1: eligible for retrofit.
Can_Retrofit = 0: not eligible for retrofit.
Retrofit{0, 1}, Flag for resource retrofit technologies (i.e., retrofit options, e.g. CCS retrofit for coal plants).
Retrofit = 1: is a retrofit technology.
Retrofit = 0: is not a retrofit technology.
Retrofit_IdUnique identifier to group retrofittable source technologies with retrofit options inside the same zone.
Retrofit_Efficiency[0,1], Efficiency of the retrofit technology.
Table 5b: Settings-specific columns in all resource .csv file

Column NameDescription
ModelingToGenerateAlternatives = 1
MGAEligibility of the technology for Modeling To Generate Alternative (MGA) run.
1 = Technology is available for the MGA run.
0 = Technology is unavailable for the MGA run (e.g. storage technologies).
Resource_TypeFor the MGA run, we categorize all the resources in a few resource types. We then find maximally different generation portfolio based on these resource types. For example, existing solar and new solar resources could be represented by a resource type names Solar. Categorization of resources into resource types is user dependent.
Maintenance data
MAINT[0,1], toggles scheduled maintenance formulation.
Maintenance_Duration(Positive integer, less than total length of simulation.) Duration of the maintenance period, in number of timesteps. Only used if MAINT=1.
Maintenance_Cycle_Length_YearsLength of scheduled maintenance cycle, in years. 1 is maintenance every year, 3 is every three years, etc. (Positive integer. Only used if MAINT=1.)
Maintenance_Begin_CadenceCadence of timesteps in which scheduled maintenance can begin. 1 means that a maintenance period can start in any timestep, 24 means it can start only in timesteps 1, 25, 49, etc. A larger number can decrease the simulation computational cost as it limits the optimizer's choices. (Positive integer, less than total length of simulation. Only used if MAINT=1.)
CO2-related parameters required if any resources have nonzero CO2CaptureFraction
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_TonCost associated with CCS disposal (/tCO2), including pipeline, injection and storage costs of CCS-equipped generators.
Table 6a: Additional columns in the Thermal.csv file
Column NameDescription
Model{1, 2}, Flag to indicate membership in set of thermal resources (e.g. nuclear, combined heat and power, natural gas combined cycle, coal power plant)
Model = 1: If the power plant relies on thermal energy input and subject unit commitment constraints/decisions if UCommit >= 1 (e.g. cycling decisions/costs/constraints).
Model = 2: If the power plant relies on thermal energy input and is subject to simplified economic dispatch constraints (ramping limits and minimum output level but no cycling decisions/costs/constraints).
Min_Power[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.
Ramp_Up_Percentage[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Ramp_Dn_Percentage[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
PiecewiseFuelUsage-related parameters
PWFU_Fuel_Usage_Zero_Load_MMBTU_per_hThe fuel usage (MMBTU/h) for the first PWFU segemnt (y-intercept) at zero load.
PWFU_Heat_Rate_MMBTU_per_MWh_*iThe slope of fuel usage function of the segment i.
PWFU_Load_Point_MW_*iThe end of segment i (MW).
Multi-fuel parameters
MULTI_FUELS{0, 1}, Flag to indicate membership in set of thermal resources that can burn multiple fuels at the same time (e.g., natural gas combined cycle cofiring with hydrogen, coal power plant cofiring with natural gas.
MULTI_FUELS = 0: Not part of set (default)
MULTI_FUELS = 1: Resources that can use fuel blending.
Num_FuelsNumber of fuels that a multi-fuel generator (MULTIFUELS = 1) can use at the same time. The length of ['Fuel1', 'Fuel2', ...] should be equal to 'Num\Fuels'. Each fuel will requires its corresponding heat rate, min cofire level, and max cofire level.
Fuel1Frist fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.
Fuel2Second fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.
Heat1_Rate_MMBTU_per_MWhHeat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel1.
Heat2_Rate_MMBTU_per_MWhHeat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel2.
Fuel1_Min_Cofire_LevelThe minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel1_Min_CofireLevel\StartThe minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Fuel1_Max_Cofire_LevelThe maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel1_Max_CofireLevel\StartThe maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Fuel2_Min_Cofire_LevelThe minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel2_Min_CofireLevel\StartThe minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Fuel2_Max_Cofire_LevelThe maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.
Fuel2_Max_CofireLevel\StartThe maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.
Table 6b: Settings-specific columns in the Thermal.csv file

Column NameDescription
UCommit >= 1The following settings apply only to thermal plants with unit commitment constraints
Up_TimeMinimum amount of time a resource has to stay in the committed state.
Down_TimeMinimum amount of time a resource has to remain in the shutdown state.
Start_Cost_per_MWCost per MW of nameplate capacity to start a generator (/MW per start). Multiplied by the number of generation units (each with a pre-specified nameplate capacity) that is turned on.
Start_Fuel_MMBTU_per_MWStartup fuel use per MW of nameplate capacity of each generator (MMBtu/MW per start).
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 7a: Additional columns in the Vre.csv file

Column NameDescription
Num_VRE_binsNumber of resource availability profiles considered for each VRE resource per zone. This parameter is used to decide the number of capacity investment decision variables related to a single variable renewable energy technology in each zone.
Num_VRE_bins = 1: using a single resource availability profile per technology per zone. 1 capacity investment decision variable and 1 generator RID tracking technology power output (and in each zone).
Num_VRE_bins > 1: using multiple resource availability profiles per technology per zone. Num_VRE_bins capacity investment decision variables and 1 generator RID used to define technology power output at each time step (and in each zone). Example: Suppose we are modeling 3 bins of wind profiles for each zone. Then include 3 rows with wind resource names as Wind_1, Wind_2, and Wind_3 and a corresponding increasing sequence of RIDs. Set Num_VRE_bins for the generator with smallest RID, Wind_1, to be 3 and set Num_VRE_bins for the other rows corresponding to Wind_2 and Wind_3, to be zero. By setting Num_VRE_bins for Wind_2 and Wind_3, the model eliminates the power outputs variables for these generators. The power output from the technology across all bins is reported in the power output variable for the first generator. This allows for multiple bins without significantly increasing number of model variables (adding each bin only adds one new capacity variable and no operational variables). See documentation for curtailable_variable_renewable() for more.
Table 6b: Settings-specific columns in the Vre.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 7a: Additional columns in the Hydro.csv file

Column NameDescription
Min_Power[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.
Ramp_Up_Percentage[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Ramp_Dn_Percentage[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Hydro_Energy_to_Power_RatioThe rated number of hours of reservoir hydro storage at peak discharge power output. (hours).
LDS{0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.
LDS = 0: Not part of set (default)
LDS = 1: Long duration storage resources
Table 7b: Settings-specific columns in the Hydro.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 8a: Additional columns in the Storage.csv file

Column NameDescription
Model{0, 1, 2}, Flag to indicate membership in set of storage resources and designate which type of storage resource formulation to employ.
Model = 0: Not part of set (default)
Model = 1: Discharging power capacity and energy capacity are the investment decision variables; symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage).
Model = 2: Discharging, charging power capacity and energy capacity are investment variables; asymmetric charge and discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
LDS{0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.
LDS = 0: Not part of set (default)
LDS = 1: Long duration storage resources
Self_Disch[0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs.
Eff_Up[0,1], Efficiency of charging storage.
Eff_Down[0,1], Efficiency of discharging storage.
Min_DurationSpecifies the minimum ratio of installed energy to discharged power capacity that can be installed (hours).
Max_DurationSpecifies the maximum ratio of installed energy to discharged power capacity that can be installed (hours).
Existing technology capacity
Existing_Cap_MWhThe existing capacity of storage in MWh where Model = 1 or Model = 2.
Existing_Charge_Cap_MWThe existing charging capacity for resources where Model = 2.
Capacity/Energy requirements
Max_Cap_MWh-1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.
Max_Charge_Cap_MW-1 (default) – no limit on maximum charge capacity of the resource. If non-negative, represents maximum allowed charge capacity (in MW) of the resource with Model = 2.
Min_Cap_MWh-1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.
Min_Charge_Cap_MW-1 (default) – no limit on minimum charge capacity of the resource. If non-negative, represents minimum allowed charge capacity (in MW) of the resource with Model = 2.
Cost parameters
Inv_Cost_per_MWhyrAnnualized investment cost of the energy capacity for a storage technology (/MW/year), applicable to either Model = 1 or Model = 2.
Inv_Cost_Charge_per_MWyrAnnualized capacity investment cost for the charging portion of a storage technology with Model = 2 (/MW/year).
Fixed_OM_Cost_per_MWhyrFixed operations and maintenance cost of the energy component of a storage technology (/MWh/year).
Fixed_OM_Cost_Charge_per_MWyrFixed operations and maintenance cost of the charging component of a storage technology of type Model = 2.
Var_OM_Cost_per_MWhInVariable operations and maintenance cost of the charging aspect of a storage technology with Model = 2. Otherwise 0 (/MWh).
Table 8b: Settings-specific columns in the Storage.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.
Table 9: Additional columns in the Flex_demand.csv file

Column NameDescription
Max_Flexible_Demand_DelayMaximum number of hours that demand can be deferred or delayed (hours).
Max_Flexible_Demand_AdvanceMaximum number of hours that demand can be scheduled in advance of the original schedule (hours).
Flexible_Demand_Energy_Eff[0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand (hours). For example, one may need to pre-cool a building more than normal to advance demand.
Cost parameters
Var_OM_Cost_per_MWhInVariable operations and maintenance costs associated with flexible demand deferral. Otherwise 0 (/MWh).
Table 10: Additional columns in the Electrolyzer.csv file

Column NameDescription
HydrogenMWhPer_TonneElectrolyzer efficiency in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced (MWh/t)
ElectrolyzerMinktMinimum annual quantity of hydrogen that must be produced by electrolyzer in kilotonnes (kt)
HydrogenPricePer_TonnePrice (or value) of hydrogen per metric tonne (/t)
Min_Power[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.
Ramp_Up_Percentage[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Ramp_Dn_Percentage[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.
Note

Check Qualified_Hydrogen_Supply column in table 5a if electrolyzers are included in the model. This column is used to indicate which resources are eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint).

Each co-located VRE and storage resource can be easily configured to contain either a co-located VRE-storage resource, standalone VRE resource (either wind, solar PV, or both), or standalone storage resource.

Table 11a: Additional columns in the Vre_stor.csv file

Column NameDescription
Technology type flags
SOLAR{0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a solar PV component.
SOLAR = 0: Not part of set (default)
SOLAR = 1: If the co-located VRE-storage resource can produce solar PV energy.
WIND{0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a wind component.
WIND = 0: Not part of set (default)
WIND = 1: If the co-located VRE-storage resource can produce wind energy.
STORDCDISCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharge behind the meter and through the inverter (DC).
STORDCDISCHARGE = 0: Not part of set (default)
STORDCDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCDISCHARGE = 1, STORDCCHARGE = 1.
STORDCDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
STORDCCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge through the inverter (DC).
STORDCCHARGE = 0: Not part of set (default)
STORDCCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCCHARGE = 1, STORDCDISCHARGE = 1.
STORDCCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
STORACDISCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharges AC.
STORACDISCHARGE = 0: Not part of set (default)
STORACDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACDISCHARGE = 1, STORACCHARGE = 1.
STORACDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
STORACCHARGE{0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge AC.
STORACCHARGE = 0: Not part of set (default)
STORACCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACCHARGE = 1, STORACDISCHARGE = 1.
STORACCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).
LDSVRESTOR{0, 1}, Flag to indicate the co-located VRE-storage resources eligible for long duration storage constraints with inter period linkage (e.g., reservoir hydro, hydrogen storage).
LDSVRESTOR = 0: Not part of set (default)
LDSVRESTOR = 1: Long duration storage resources
Existing technology capacity
Existing_Cap_MWThe existing AC grid connection capacity in MW.
Existing_Cap_MWhThe existing capacity of storage in MWh.
Existing_Cap_Inverter_MWThe existing capacity of co-located VRE-STOR resource's inverter in MW (AC).
Existing_Cap_Solar_MWThe existing capacity of co-located VRE-STOR resource's solar PV in MW (DC).
Existing_Cap_Wind_MWThe existing capacity of co-located VRE-STOR resource's wind in MW (AC).
Existing_Cap_Discharge_DC_MWThe existing discharge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_DISCHARGE = 2.
Existing_Cap_Charge_DC_MWThe existing charge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_CHARGE = 2.
Existing_Cap_Discharge_AC_MWThe existing discharge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_AC_DISCHARGE = 2.
Existing_Cap_Charge_AC_MWThe existing charge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_DC_CHARGE = 2.
Capacity/Energy requirements
Max_Cap_MW-1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed AC grid connection capacity in MW of the resource.
Max_Cap_MWh-1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity of storage in MWh.
Min_Cap_MW-1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed AC grid connection capacity in MW.
Min_Cap_MWh-1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity of storage in MWh.
Max_Cap_Inverter_MW-1 (default) – no limit on maximum inverter capacity of the resource. If non-negative, represents maximum allowed inverter capacity (in MW AC) of the resource.
Max_Cap_Solar_MW-1 (default) – no limit on maximum solar PV capacity of the resource. If non-negative, represents maximum allowed solar PV capacity (in MW DC) of the resource.
Max_Cap_Wind_MW-1 (default) – no limit on maximum wind capacity of the resource. If non-negative, represents maximum allowed wind capacity (in MW AC) of the resource.
Max_Cap_Discharge_DC_MW-1 (default) – no limit on maximum DC discharge capacity of the resource. If non-negative, represents maximum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.
Max_Cap_Charge_DC_MW-1 (default) – no limit on maximum DC charge capacity of the resource. If non-negative, represents maximum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.
Max_Cap_Discharge_AC_MW-1 (default) – no limit on maximum AC discharge capacity of the resource. If non-negative, represents maximum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.
Max_Cap_Charge_AC_MW-1 (default) – no limit on maximum AC charge capacity of the resource. If non-negative, represents maximum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.
Min_Cap_Inverter_MW-1 (default) – no limit on minimum inverter capacity of the resource. If non-negative, represents minimum allowed inverter capacity (in MW AC) of the resource.
Min_Cap_Solar_MW-1 (default) – no limit on minimum solar PV capacity of the resource. If non-negative, represents minimum allowed solar PV capacity (in MW DC) of the resource.
Min_Cap_Wind_MW-1 (default) – no limit on minimum wind capacity of the resource. If non-negative, represents minimum allowed wind capacity (in MW AC) of the resource.
Min_Cap_Discharge_DC_MW-1 (default) – no limit on minimum DC discharge capacity of the resource. If non-negative, represents minimum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.
Min_Cap_Charge_DC_MW-1 (default) – no limit on minimum DC charge capacity of the resource. If non-negative, represents minimum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.
Min_Cap_Discharge_AC_MW-1 (default) – no limit on minimum AC discharge capacity of the resource. If non-negative, represents minimum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.
Min_Cap_Charge_AC_MW-1 (default) – no limit on minimum AC charge capacity of the resource. If non-negative, represents minimum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.
Cost parameters
Inv_Cost_per_MWyrAnnualized capacity investment cost of the grid connection (/MW/year).
Inv_Cost_per_MWhyrAnnualized investment cost of the energy capacity for the co-located storage resource (/MW/year)
Fixed_OM_Cost_per_MWyrFixed operations and maintenance cost of the grid connection (/MW/year).
Fixed_OM_Cost_per_MWhyrFixed operations and maintenance cost of the energy component of the co-located storage resource. (/MWh/year).
Inv_Cost_Inverter_per_MWyrAnnualized capacity investment cost of the inverter component (/MW-AC/year).
Inv_Cost_Solar_per_MWyrAnnualized capacity investment cost of the solar PV component (/MW-DC/year).
Inv_Cost_Wind_per_MWyrAnnualized capacity investment cost of the wind component (/MW-AC/year).
Inv_Cost_Discharge_DC_per_MWyrAnnualized capacity investment cost for the discharging portion of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).
Inv_Cost_Charge_DC_per_MWyrAnnualized capacity investment cost for the charging portion of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).
Inv_Cost_Discharge_AC_per_MWyrAnnualized capacity investment cost for the discharging portion of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).
Inv_Cost_Charge_AC_per_MWyrAnnualized capacity investment cost for the charging portion of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).
Fixed_OM_Inverter_Cost_per_MWyrFixed operations and maintenance cost of the inverter component (/MW-AC/year).
Fixed_OM_Solar_Cost_per_MWyrFixed operations and maintenance cost of the solar PV component (/MW-DC/year).
Fixed_OM_Wind_Cost_per_MWyrFixed operations and maintenance cost of the wind component (/MW-AC/year).
Fixed_OM_Cost_Discharge_DC_per_MWyrFixed operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).
Fixed_OM_Cost_Charge_DC_per_MWyrFixed operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).
Fixed_OM_Cost_Discharge_AC_per_MWyrFixed operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).
Fixed_OM_Cost_Charge_AC_per_MWyrFixed operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).
Var_OM_Cost_per_MWh_SolarVariable operations and maintenance cost of the solar PV component (multiplied by the inverter efficiency for AC terms) (/MWh).
Var_OM_Cost_per_MWh_WindVariable operations and maintenance cost of the wind component (/MWh).
Var_OM_Cost_per_MWh_Discharge_DCVariable operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (multiplied by the inverter efficiency for AC terms) (/MWh).
Var_OM_Cost_per_MWh_Charge_DCVariable operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (divided by the inverter efficiency for AC terms) (/MWh).
Var_OM_Cost_per_MWh_Discharge_ACVariable operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MWh).
Var_OM_Cost_per_MWh_Charge_ACVariable operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MWh).
Technical performance parameters
Self_Disch[0,1], The power loss of storage component of each resource per hour (fraction loss per hour).
EtaInverter[0,1], Inverter efficiency representing losses from converting DC to AC power and vice versa for each technology
InverterRatioSolar-1 (default) - no required ratio between solar PV capacity built to inverter capacity built. If non-negative, represents the ratio of solar PV capacity built to inverter capacity built.
InverterRatioWind-1 (default) - no required ratio between wind capacity built to grid connection capacity built. If non-negative, represents the ratio of wind capacity built to grid connection capacity built.
Power_to_Energy_ACThe power to energy conversion for the storage component for AC discharging/charging of symmetric storage resources.
Power_to_Energy_DCThe power to energy conversion for the storage component for DC discharging/charging of symmetric storage resources.
Eff_Up_DC[0,1], Efficiency of DC charging storage – applies to storage technologies (all STOR types).
Eff_Down_DC[0,1], Efficiency of DC discharging storage – applies to storage technologies (all STOR types).
Eff_Up_AC[0,1], Efficiency of AC charging storage – applies to storage technologies (all STOR types).
Eff_Down_AC[0,1], Efficiency of AC discharging storage – applies to storage technologies (all STOR types).
Table 11b: Settings-specific columns in the Vre_stor.csv file

Column NameDescription
OperationalReserves = 1
Reg_CostCost of providing regulation reserves (/MW per time step/hour).
Rsv_CostCost of providing upwards spinning or contingency reserves (/MW per time step/hour).
Reg_Max[0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .
Rsv_Max[0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.

In addition to the files described above, the resources folder contains the following files that are used to specify policy-related parameters for specific resources:

  1. Resource_energy_share_requirement.csv
  2. Resource_minimum_capacity_requirement.csv
  3. Resource_maximum_capacity_requirement.csv
  4. Resource_capacity_reserve_margin.csv
Note

These files are optional and can be omitted if no policy-related parameters are specified in the settings file. Also, not all the resources need to be included in these files, only those for which the policy applies.

The following table describes the columns in each of these four files.

Warning

The first column of each file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in the policy files is not important.

This policy is applied when if EnergyShareRequirement > 0 in the settings file. * corresponds to the ith row of the file Energy_share_requirement.csv.

Table 12: Energy share requirement policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
ESR_*Flag to indicate which resources are considered for the Energy Share Requirement constraint.
1- included
0- excluded
co-located VRE-STOR resources only
ESRVreStor_*Flag to indicate which resources are considered for the Energy Share Requirement constraint.
1- included
0- excluded

This policy is applied when if MinCapReq = 1 in the settings file. * corresponds to the ith row of the file Minimum_capacity_requirement.csv.

Table 13: Minimum capacity requirement policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
MinCap\*Flag to indicate which resources are considered for the Minimum Capacity Requirement constraint.
co-located VRE-STOR resources only
MinCapSolar_*Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Minimum Technology Carveout constraint.
MinCapWind_*Eligibility of resources with a wind component to participate in Minimum Technology Carveout constraint (AC terms).
MinCapStor_*Eligibility of resources with a storage component to participate in Minimum Technology Carveout constraint (discharge capacity in AC terms).

This policy is applied when if MaxCapReq = 1 in the settings file. * corresponds to the ith row of the file Maximum_capacity_requirement.csv.

Table 14: Maximum capacity requirement policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
MaxCap\*Flag to indicate which resources are considered for the Maximum Capacity Requirement constraint.
co-located VRE-STOR resources only
MaxCapSolar_*Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Maximum Technology Carveout constraint.
MaxCapWind_*Eligibility of resources with a wind component to participate in Maximum Technology Carveout constraint (AC terms).
MaxCapStor_*Eligibility of resources with a storage component to participate in Maximum Technology Carveout constraint (discharge capacity in AC terms).

This policy is applied when if CapacityReserveMargin > 0 in the settings file. * corresponds to the ith row of the file Capacity_reserve_margin.csv.

Table 15: Capacity reserve margin policy parameters

Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
EligibleCapRes_*Fraction of the resource capacity eligible for contributing to the capacity reserve margin constraint (e.g. derate factor).

In addition to the files described above, the resources folder can contain additional files that are used to specify attributes for specific resources and modules. Currently, the following files are supported:

  1. Resource_multistage_data.csv: mandatory if MultiStage = 1 in the settings file

<!– 2) Resource_piecewisefuel_usage.csv –>

Warning

The first column of each additional module file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in these files is not important.

Table 16: Multistage parameters
Warning

This file is mandatory if MultiStage = 1 in the settings file.


Column NameDescription
ResourceResource name corresponding to a resource in one of the resource data files described above.
Capital_Recovery_PeriodCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.
LifetimeLifetime (in years) used for determining endogenous retirements of newly built capacity. Note that the same lifetime is used for each component of a co-located VRE-STOR resource.
Min_Retired_Cap_MWMinimum required discharge capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.
Min_Retired_Energy_Cap_MWMinimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing energy capacity. Note that for co-located VRE-STOR resources, this value pertains to the storage component.
Min_Retired_Charge_Cap_MWMinimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing charge capacity.
Contribute_Min_Retirement{0, 1}, Flag to indicate whether the (retrofitting) resource can contribute to the minimum retirement requirement.
co-located VRE-STOR resources only
Capital_Recovery_Period_DCCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the inverter component.
Capital_Recovery_Period_SolarCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the solar PV component.
Capital_Recovery_Period_WindCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the wind component.
Capital_Recovery_PeriodDischargeDCCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge DC component when STOR_DC_DISCHARGE = 2.
Capital_Recovery_PeriodChargeDCCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge DC component when STOR_DC_CHARGE = 2.
Capital_Recovery_PeriodDischargeACCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge AC component when STOR_AC_DISCHARGE = 2.
Capital_Recovery_PeriodChargeACCapital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge AC component when STOR_AC_CHARGE = 2.
Min_Retired_Cap_Inverter_MWMinimum required inverter capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_Solar_MWMinimum required solar capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_Wind_MWMinimum required wind capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_DischargeDC\MWMinimum required discharge capacity retirements in the current model period for storage resources with STOR_DC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_ChargeDC\MWMinimum required charge capacity retirements in the current model period for storage resources with STOR_DC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_DischargeAC\MWMinimum required discharge capacity retirements in the current model period for storage resources with STOR_AC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
Min_Retired_Cap_ChargeAC\MWMinimum required charge capacity retirements in the current model period for storage resources with STOR_AC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.
WACC_DCThe line-specific weighted average cost of capital for the inverter component.
WACC_SolarThe line-specific weighted average cost of capital for the solar PV component.
WACC_WindThe line-specific weighted average cost of capital for the wind component.
WACC_Discharge_DCThe line-specific weighted average cost of capital for the discharging DC storage component with STOR_DC_DISCHARGE = 2.
WACC_Charge_DCThe line-specific weighted average cost of capital for the charging DC storage component with STOR_DC_CHARGE = 2.
WACC_Discharge_ACThe line-specific weighted average cost of capital for the discharging AC storage component with STOR_AC_DISCHARGE = 2.
WACC_Charge_ACThe line-specific weighted average cost of capital for the charging AC storage component with STOR_AC_CHARGE = 2.

1.5 Generator_variability.csv

This file contains the time-series of capacity factors / availability of each resource included in the resource .csv file in the resources folder for each time step (e.g. hour) modeled.

• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.

• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the resource .csv file in the resources folder in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in the resource .csv file must be unique. Note that for Hydro reservoir resources (i.e. Hydro.csv), values in this file correspond to inflows (in MWhs) to the hydro reservoir as a fraction of installed power capacity, rather than hourly capacity factor. Note that for co-located VRE and storage resources, solar PV and wind resource profiles should not be located in this file but rather in separate variability files (these variabilities can be in the Generators_variability.csv if time domain reduction functionalities will be utilized because the time domain reduction functionalities will separate the files after the clustering is completed).

|Self_Disch |[0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs. Note that for co-located VRE-STOR resources, this value applies to the storage component of each resource.| |Min_Power |[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Up_Percentage |[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Dn_Percentage |[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Eff_Up |[0,1], Efficiency of charging storage – applies to storage technologies (all STOR types except co-located storage resources).| |Eff_Down |[0,1], Efficiency of discharging storage – applies to storage technologies (all STOR types except co-located storage resources). |

|Min_Duration |Specifies the minimum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Duration |Specifies the maximum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Flexible_Demand_Delay |Maximum number of hours that demand can be deferred or delayed. Applies to resources with FLEX type 1 (hours). | |Max_Flexible_Demand_Advance |Maximum number of hours that demand can be scheduled in advance of the original schedule. Applies to resources with FLEX type 1 (hours). | |Flexible_Demand_Energy_Eff |[0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand. Applies to resources with FLEX type 1 (hours). For example, one may need to pre-cool a building more than normal to advance demand. |

1.6 Vre_and_stor_solar_variability.csv

This file contains the time-series of capacity factors / availability of the solar PV component (DC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.

• first column: The first column contains the time index of each row (starting in the second row) from 1 to N.

• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique.

1.7 Vre_and_stor_wind_variability.csv

This file contains the time-series of capacity factors / availability of the wind component (AC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.

• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.

• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique.

2. Optional inputs files

2.1 Operational_reserves.csv

This file includes parameter inputs needed to model time-dependent procurement of regulation and spinning reserves. This file is needed if OperationalReserves flag is activated in the YAML file genx_settings.yml.

Table 7: Structure of the Operational_reserves.csv file

Column NameDescription
Reg_Req_Percent_Demand[0,1], Regulation requirement as a percent of time-dependent demand; here demand is the total across all model zones.
Reg_Req_Percent_VRE[0,1], Regulation requirement as a percent of time-dependent wind and solar generation (summed across all model zones).
Rsv_Req_Percent_Demand [0,1],Spinning up or contingency reserve requirement as a percent of time-dependent demand (which is summed across all zones).
Rsv_Req_Percent_VRE[0,1], Spinning up or contingency reserve requirement as a percent of time-dependent wind and solar generation (which is summed across all zones).
Unmet_Rsv_Penalty_Dollar_per_MWPenalty for not meeting time-dependent spinning reserve requirement (/MW per time step).
Dynamic_ContingencyFlags to include capacity (generation or transmission) contingency to be added to the spinning reserve requirement.
Dynamic_Contingency= 1: contingency set to be equal to largest installed thermal unit (only applied when UCommit = 1).
= 2: contingency set to be equal to largest committed thermal unit each time period (only applied when UCommit = 1).
Static_Contingency_MWA fixed static contingency in MW added to reserve requirement. Applied when UCommit = 1 and DynamicContingency = 0, or when UCommit = 2. Contingency term not included in operating reserve requirement when this value is set to 0 and DynamicContingency is not active.

2.2 Energy_share_requirement.csv

This file contains inputs specifying minimum energy share requirement policies, such as Renewable Portfolio Standard (RPS) or Clean Energy Standard (CES) policies. This file is needed if parameter EnergyShareRequirement has a non-zero value in the YAML file genx_settings.yml.

Note: this file should use the same region name as specified in the the resource .csv file (inside the Resource).

Table 8: Structure of the Energy_share_requirement.csv file

Column NameDescription
Region_descriptionRegion name
Network_zoneszone number represented as z*
ESR_*[0,1], Energy share requirements as a share of zonal demand (calculated on an annual basis). * represents the number of the ESR constraint, given by the number of ESR_* columns in the Energy_share_requirement.csv file.

2.3 CO2_cap.csv

This file contains inputs specifying CO2 emission limits policies (e.g. emissions cap and permit trading programs). This file is needed if CO2Cap flag is activated in the YAML file genx_settings.yml. CO2Cap flag set to 1 represents mass-based (tCO2 ) emission target. CO2Cap flag set to 2 is specified when emission target is given in terms of rate (tCO2/MWh) and is based on total demand met. CO2Cap flag set to 3 is specified when emission target is given in terms of rate (tCO2 /MWh) and is based on total generation.

Table 9: Structure of the CO2_cap.csv file

Column NameDescription
Region_descriptionRegion name
Network_zoneszone number represented as z*
CO_2_Cap_Zone_*If a zone is eligible for the emission limit constraint, then this column is set to 1, else 0.
CO_2_Max_tons_MWh_*Emission limit in terms of rate
CO_2_Max_Mtons_*Emission limit in absolute values, in Million of tons
where in the above inputs, * represents the number of the emission limit constraints. For example, if the model has 2 emission limit constraints applied separately for 2 zones, the above CSV file will have 2 columns for specifying emission limit in terms on rate: CO_2_Max_tons_MWh_1 and CO_2_Max_tons_MWh_2.

2.4 Capacity_reserve_margin.csv

This file contains the regional capacity reserve margin requirements. This file is needed if parameter CapacityReserveMargin has a non-zero value in the YAML file genx_settings.yml.

Note: this file should use the same region name as specified in the resource .csv file (inside the Resource).

Table 10: Structure of the Capacity_reserve_margin.csv file

Column NameDescription
Region_descriptionRegion name
Network_zoneszone number represented as z*
CapRes_*[0,1], Capacity reserve margin requirements of a zone, reported as a fraction of demand

2.5 Minimum_capacity_requirement.csv

This file contains the minimum capacity carve-out requirement to be imposed (e.g. a storage capacity mandate or offshore wind capacity mandate). This file is needed if the MinCapReq flag has a non-zero value in the YAML file genx_settings.yml.

Table 11: Structure of the Minimum_capacity_requirement.csv file

Column NameDescription
MinCapReqConstraintIndex of the minimum capacity carve-out requirement.
Constraint_DescriptionNames of minimum capacity carve-out constraints; not to be read by model, but used as a helpful notation to the model user.
Min_MWminimum capacity requirement [MW]

Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.

2.6 Maximum_capacity_requirement.csv

This contains the maximum capacity limits to be imposed (e.g. limits on total deployment of solar, wind, or batteries in the system as a whole or in certain collections of zones). It is required if the MaxCapReq flag has a non-zero value in genx_settings.yml.

Table 12: Structure of the Maximum_capacity_requirement.csv file

Column NameDescription
MaxCapReqConstraintIndex of the maximum capacity limit.
Constraint_DescriptionNames of maximum capacity limit; not to be read by model, but used as a helpful notation to the model user.
Max_MWmaximum capacity limit [MW]

Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.

2.7 Method_of_morris_range.csv

This file contains the settings parameters required to run the Method of Morris algorithm in GenX. This file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.

Table 13: Structure of the Method_of_morris_range.csv file

Column NameDescription
ResourceThis column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand/loads.
ZoneInteger representing zone number where the resource is located.
Lower_boundPercentage lower deviation from the nominal value
Upper_boundPercentage upper deviation from the nominal value
ParameterColumn from the resource .csv file (inside the Resource) containing uncertain parameters
GroupGroup the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined
p_stepsNumber of steps between upper and lower bound
total_num_trajectoryTotal number of trakectories through the design matrix
num_trajectorySelected number of trajectories throigh the design matrix
len_design_matLength of the design matrix
policyName of the policy
Notes
  1. Upper and lower bounds are specified in terms of percentage deviation from the nominal value.
  2. Percentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lowerbound and Upperbound must be identical
  3. P_steps should at least be = 1\%, i.e., Upper_bound – Lower_bound $<$ p_steps
  4. P_steps for parameters in one group must be identical
  5. Total_num_trajectory should be around 3 to 4 times the total number of uncertain parameters
  6. num_trajectory should be approximately equal to the total number of uncertain parameters
  7. len_design_mat should be 1.5 to 2 times the total number of uncertain parameters
  8. Higher number of num_trajectory and lendesignmat would lead to higher accuracy
  9. Upper and lower bounds should be specified for all the resources included in the resource .csv file (inside the Resource). If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.
diff --git a/previews/PR655/User_Guide/model_output/index.html b/previews/PR655/User_Guide/model_output/index.html index e30520e835..564a288523 100644 --- a/previews/PR655/User_Guide/model_output/index.html +++ b/previews/PR655/User_Guide/model_output/index.html @@ -1,2 +1,2 @@ -Model Outputs · GenX

GenX Outputs

The table below summarizes the units of each output variable reported as part of the various CSV files produced after each model run. The reported units are also provided. If a result file includes time-dependent values, the value will not include the hour weight in it. An annual sum ("AnnualSum") column/row will be provided whenever it is possible (e.g., emissions.csv).

1 Default output files

1.1 capacity.csv

Reports optimal values of investment variables (except StartCap, which is an input)

Table 15: Structure of the capacity.csv file

OutputDescriptionUnits
StartCapInitial power capacity of each resource type in each zone; this is an inputMW
RetCapRetired power capacity of each resource type in each zoneMW
NewCapInstalled capacity of each resource type in each zoneMW
EndCapTotal power capacity of each resource type in each zoneMW
StartEnergyCapInitial energy capacity of each resource type in each zone; this is an input and applies only to storage tech.MWh
RetEnergyCapRetired energy capacity of each resource type in each zone; applies only to storage tech.MWh
NewEnergyCapInstalled energy capacity of each resource type in each zone; applies only to storage tech.MWh
EndEnergyCapTotal installed energy capacity of each resource type in each zone; applies only to storage tech.MWh
StartChargeCapInitial charging power capacity of STOR = 2 resource type in each zone; this is an inputMW
RetChargeCapRetired charging power capacity of STOR = 2 resource type in each zoneMW
NewChargeCapInstalled charging capacity of each resource type in each zoneMW
EndChargeCapTotal charging power capacity of each resource type in each zoneMW

1.2 costs.csv

Reports optimal objective function value and contribution of each term by zone.

Table 16: Structure of the costs.csv file

OutputDescriptionUnits
cTotalTotal objective function value$
cFixTotal annualized investment and fixed operating & maintainenance (FOM) costs associated with all resources$
cVarTotal annual variable cost associated with all resources; includes fuel costs for thermal plants$
cNSETotal annual cost of non-served energy$
cStartTotal annual cost of start-up of thermal power plants$
cUnmetRsvTotal annual cost of not meeting time-dependent operating reserve (spinning) requirements$
cNetworkExpTotal cost of network expansion$
cEmissionsRevenueTotal and zonal emissions revenue$
cEmissionsCostTotal an zonal emissions cost$

1.3 emissions.csv

Reports CO2 emissions by zone at each hour; an annual sum row will be provided. If any emission cap is present, emission prices each zone faced by each cap will be copied on top of this table with the following strucutre.

Table 17: Structure of emission prices in the emissions.csv file

OutputDescriptionUnits
CO2\priceMarginal CO2 abatement cost associated with constraint on maximum annual CO2 emissions; will be same across zones if CO2 emissions constraint is applied for the entire region and not zone-wise$/ tonne CO2.

1.4 nse.csv

Reports non-served energy for every model zone, time step and cost-segment.

1.5 power.csv

Reports power discharged by each resource (generation, storage, demand response) in each model time step.

1.6 reliability.csv

Reports dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.

1.7 prices.csv

Reports marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the load balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.

1.8 status.csv

Reports computational performance of the model and objective function related information.

Table 18: Structure of the status.csv file

OutputDescriptionUnits
Statustermination criteria (optimal, timelimit etc.).
solveSolve time including time for pre-solveseconds
ObjvalOptimal objective function value$
ObjboundBest objective lower bound$
FinalMIPGapOptimality gap at termination in case of a mixed-integer linear program (MIP gap); when using Gurobi, the lower bound and MIP gap is reported excluding constant terms (E.g. fixed cost of existing generators that cannot be retired) in the objective function and hence may not be directly usable.Fraction

1.9 NetRevenue.csv

This file summarizes the cost, revenue and profit for each generation technology for each region.

Table 19: Stucture of the NetRevenue.csv file

OutputDescriptionUnits
Fixed_OM_cost_MWFixed Operation and Maintenance cost of the MW capacity.$
Fixed_OM_cost_MWhFixed Operation and Maintenance cost of the MWh capacity. Only applicable to energy storage.$
Var_OM_cost_outVariable Operation and Maintenance cost of the power generation or discharge.$
Var_OM_cost_inVariable Operation and Maintenance cost of the power charge/pumping. Only applicable to energy storage.$
Fuel_costFuel cost of the power generation. Only applicable to generation that burns fuel.$
Charge_costCost of charging power (due to the payment for electricity) Only applicable to energy storage.$
EmissionsCostCost of buying emission credit.$
StartCostCost of generator start-up.$
Inv_cost_MWCost of building MW capacity.$
Inv_cost_MWhCost of building MWh capacity.$
EnergyRevenueRevenue of generating power.$
SubsidyRevenueRevenue of Min_Cap subsidy.$
ReserveMarginRevenueRevenue earned from capacity reserve margin constraints.$
ESRRevenueRevenue selling renewable/clean energy credits.$
RevenueTotal Revenue.$
CostTotal Cost.$
ProfitRevenue minus Cost.$

2 Settings-specific outputs

This section includes the output files that GenX will print if corresponding function is specified in the Settings.

2.1 CapacityValue.csv

This file includes the time-dependent capacity value calculated for each generator. GenX will print this file only if the capacity reserve margin constraints are modeled through the setting file. Each row of the file (excluding the header) corresponds to a generator specified in the inputs. Each column starting from the t1 to the second last one stores the result of capacity obligation provided in each hour divided by the total capacity. Thus the number is unitless. If the capacity margin reserve is not binding for one hour, GenX will return zero. The last column specified the name of the corresponding capacity reserve constraint. Note that, if the user calculates the hour-weight-averaged capacity value for each generator using data of the binding hours, the result is what RTO/ISO call capacity credit.

<!– #### 2.2 ExportRevenue.csv

This file includes the export revenue in $ of each zone. GenX will print this file only when a network is present and Locational Marginal Price (LMP) data is available to the GenX. The Total row includes the time-step-weighted summation of the time-dependent values shown below. For each time-step, the export revenue is calculated as the net outbound powerflow multiplied by the LMP. It is noteworthy that this export revenue is already part of the generation revenue, and the user should not double count.

2.3 Importcost.csv

This file includes the import cost in $ of each zone. GenX will print this file only when a network is present and Locational Marginal Price (LMP) data is available to the GenX. The Total row includes the time-step -weighted summation of the time-dependent values shown below. For each time step, the import cost is calculated as the net inbound powerflow multiplied by the LMP. It is noteworthy that this import cost is already part of the load payment, and the user should not double count. –>

2.2 EnergyRevenue.csv

This file includes the energy revenue in $ earned by each generator through injecting into the grid. Only annual sum values are available.

2.3 ChargingCost.csv

This file includes the charging cost in $ of earned by each generator through withdrawing from the grid. Only annual sum values are available.

2.4 ReserveMargin.csv

This file includes the shadow prices of the capacity reserve margin constraints. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver, as described earlier. Each row (except the header) corresponds to a capacity reserve margin constraint, and each column corresponds to an time step. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

2.5 ReserveMarginRevenue.csv

This file includes the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

2.6 ESR_prices.csv

This file includes the renewable/clean energy credit price of each modeled RPS/CES constraint. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. The unit is /MWh.

2.7 ESR_Revenue.csv

This file includes the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.

2.8 SubsidyRevenue.csv

This file includes subsidy revenue earned if a generator specified Min_Cap is provided in the input file. GenX will print this file only the shadow price can be obtained form the solver. Do not confuse this with the Minimum Capacity Carveout constraint, which is for a subset of generators, and a separate revenue term will be calculated in other files. The unit is $.

+Model Outputs · GenX

GenX Outputs

The table below summarizes the units of each output variable reported as part of the various CSV files produced after each model run. The reported units are also provided. If a result file includes time-dependent values, the value will not include the hour weight in it. An annual sum ("AnnualSum") column/row will be provided whenever it is possible (e.g., emissions.csv).

1 Default output files

1.1 capacity.csv

Reports optimal values of investment variables (except StartCap, which is an input)

Table 15: Structure of the capacity.csv file

OutputDescriptionUnits
StartCapInitial power capacity of each resource type in each zone; this is an inputMW
RetCapRetired power capacity of each resource type in each zoneMW
NewCapInstalled capacity of each resource type in each zoneMW
EndCapTotal power capacity of each resource type in each zoneMW
StartEnergyCapInitial energy capacity of each resource type in each zone; this is an input and applies only to storage tech.MWh
RetEnergyCapRetired energy capacity of each resource type in each zone; applies only to storage tech.MWh
NewEnergyCapInstalled energy capacity of each resource type in each zone; applies only to storage tech.MWh
EndEnergyCapTotal installed energy capacity of each resource type in each zone; applies only to storage tech.MWh
StartChargeCapInitial charging power capacity of STOR = 2 resource type in each zone; this is an inputMW
RetChargeCapRetired charging power capacity of STOR = 2 resource type in each zoneMW
NewChargeCapInstalled charging capacity of each resource type in each zoneMW
EndChargeCapTotal charging power capacity of each resource type in each zoneMW

1.2 costs.csv

Reports optimal objective function value and contribution of each term by zone.

Table 16: Structure of the costs.csv file

OutputDescriptionUnits
cTotalTotal objective function value$
cFixTotal annualized investment and fixed operating & maintainenance (FOM) costs associated with all resources$
cVarTotal annual variable cost associated with all resources; includes fuel costs for thermal plants$
cNSETotal annual cost of non-served energy$
cStartTotal annual cost of start-up of thermal power plants$
cUnmetRsvTotal annual cost of not meeting time-dependent operating reserve (spinning) requirements$
cNetworkExpTotal cost of network expansion$
cEmissionsRevenueTotal and zonal emissions revenue$
cEmissionsCostTotal an zonal emissions cost$

1.3 emissions.csv

Reports CO2 emissions by zone at each hour; an annual sum row will be provided. If any emission cap is present, emission prices each zone faced by each cap will be copied on top of this table with the following strucutre.

Table 17: Structure of emission prices in the emissions.csv file

OutputDescriptionUnits
CO2\priceMarginal CO2 abatement cost associated with constraint on maximum annual CO2 emissions; will be same across zones if CO2 emissions constraint is applied for the entire region and not zone-wise$/ tonne CO2.

1.4 nse.csv

Reports non-served energy for every model zone, time step and cost-segment.

1.5 power.csv

Reports power discharged by each resource (generation, storage, demand response) in each model time step.

1.6 reliability.csv

Reports dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.

1.7 prices.csv

Reports marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the load balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.

1.8 status.csv

Reports computational performance of the model and objective function related information.

Table 18: Structure of the status.csv file

OutputDescriptionUnits
Statustermination criteria (optimal, timelimit etc.).
solveSolve time including time for pre-solveseconds
ObjvalOptimal objective function value$
ObjboundBest objective lower bound$
FinalMIPGapOptimality gap at termination in case of a mixed-integer linear program (MIP gap); when using Gurobi, the lower bound and MIP gap is reported excluding constant terms (E.g. fixed cost of existing generators that cannot be retired) in the objective function and hence may not be directly usable.Fraction

1.9 NetRevenue.csv

This file summarizes the cost, revenue and profit for each generation technology for each region.

Table 19: Stucture of the NetRevenue.csv file

OutputDescriptionUnits
Fixed_OM_cost_MWFixed Operation and Maintenance cost of the MW capacity.$
Fixed_OM_cost_MWhFixed Operation and Maintenance cost of the MWh capacity. Only applicable to energy storage.$
Var_OM_cost_outVariable Operation and Maintenance cost of the power generation or discharge.$
Var_OM_cost_inVariable Operation and Maintenance cost of the power charge/pumping. Only applicable to energy storage.$
Fuel_costFuel cost of the power generation. Only applicable to generation that burns fuel.$
Charge_costCost of charging power (due to the payment for electricity) Only applicable to energy storage.$
EmissionsCostCost of buying emission credit.$
StartCostCost of generator start-up.$
Inv_cost_MWCost of building MW capacity.$
Inv_cost_MWhCost of building MWh capacity.$
EnergyRevenueRevenue of generating power.$
SubsidyRevenueRevenue of Min_Cap subsidy.$
ReserveMarginRevenueRevenue earned from capacity reserve margin constraints.$
ESRRevenueRevenue selling renewable/clean energy credits.$
RevenueTotal Revenue.$
CostTotal Cost.$
ProfitRevenue minus Cost.$

2 Settings-specific outputs

This section includes the output files that GenX will print if corresponding function is specified in the Settings.

2.1 CapacityValue.csv

This file includes the time-dependent capacity value calculated for each generator. GenX will print this file only if the capacity reserve margin constraints are modeled through the setting file. Each row of the file (excluding the header) corresponds to a generator specified in the inputs. Each column starting from the t1 to the second last one stores the result of capacity obligation provided in each hour divided by the total capacity. Thus the number is unitless. If the capacity margin reserve is not binding for one hour, GenX will return zero. The last column specified the name of the corresponding capacity reserve constraint. Note that, if the user calculates the hour-weight-averaged capacity value for each generator using data of the binding hours, the result is what RTO/ISO call capacity credit.

<!– #### 2.2 ExportRevenue.csv

This file includes the export revenue in $ of each zone. GenX will print this file only when a network is present and Locational Marginal Price (LMP) data is available to the GenX. The Total row includes the time-step-weighted summation of the time-dependent values shown below. For each time-step, the export revenue is calculated as the net outbound powerflow multiplied by the LMP. It is noteworthy that this export revenue is already part of the generation revenue, and the user should not double count.

2.3 Importcost.csv

This file includes the import cost in $ of each zone. GenX will print this file only when a network is present and Locational Marginal Price (LMP) data is available to the GenX. The Total row includes the time-step -weighted summation of the time-dependent values shown below. For each time step, the import cost is calculated as the net inbound powerflow multiplied by the LMP. It is noteworthy that this import cost is already part of the load payment, and the user should not double count. –>

2.2 EnergyRevenue.csv

This file includes the energy revenue in $ earned by each generator through injecting into the grid. Only annual sum values are available.

2.3 ChargingCost.csv

This file includes the charging cost in $ of earned by each generator through withdrawing from the grid. Only annual sum values are available.

2.4 ReserveMargin.csv

This file includes the shadow prices of the capacity reserve margin constraints. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver, as described earlier. Each row (except the header) corresponds to a capacity reserve margin constraint, and each column corresponds to an time step. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

2.5 ReserveMarginRevenue.csv

This file includes the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.

2.6 ESR_prices.csv

This file includes the renewable/clean energy credit price of each modeled RPS/CES constraint. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. The unit is /MWh.

2.7 ESR_Revenue.csv

This file includes the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.

2.8 SubsidyRevenue.csv

This file includes subsidy revenue earned if a generator specified Min_Cap is provided in the input file. GenX will print this file only the shadow price can be obtained form the solver. Do not confuse this with the Minimum Capacity Carveout constraint, which is for a subset of generators, and a separate revenue term will be calculated in other files. The unit is $.

diff --git a/previews/PR655/User_Guide/multi_stage_input/index.html b/previews/PR655/User_Guide/multi_stage_input/index.html index 7dffccf7d9..0ac238329c 100644 --- a/previews/PR655/User_Guide/multi_stage_input/index.html +++ b/previews/PR655/User_Guide/multi_stage_input/index.html @@ -20,4 +20,4 @@ ─────────────────-┼────────────────────┼────────────────────────── coal_1 │ 4500 │ 0 20_NH3_retrofit_1 │ 0 │ 0 <--------- -20_NH3_retrofit_2 │ 0 │ 0 <---------

And the case where some retrofit options contribute to the minimum retirement requirement and some do not is not currently supported and will be addressed in a future release.

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.

multi_stage_settings.yml
NumStagesThe number of model investment planning stages.
StageLengthsA list of lengths of each model stage in years (e.g., [10, 10, 10] for three stages each of length 10). Note that stages could be defined to be of varying length.
Myopic0 = perfect foresight, 1 = myopic model (see above table)
ConvergenceToleranceThe relative optimality gap used for convergence of the dual dynamic programming algorithm. Only required when Myopic = 0
WACCRate used to discount non-technology-specific costs from stage to stage (i.e., the “social discount rate”).
time_domain_reduction_settings.yml
MultiStageConcatenateDesignates whether to use time domain reduction for the full set of input data together (1) or to reduce only the first stage data and apply the returned representative periods to the rest of the input data (0).
+20_NH3_retrofit_2 │ 0 │ 0 <---------

And the case where some retrofit options contribute to the minimum retirement requirement and some do not is not currently supported and will be addressed in a future release.

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.

multi_stage_settings.yml
NumStagesThe number of model investment planning stages.
StageLengthsA list of lengths of each model stage in years (e.g., [10, 10, 10] for three stages each of length 10). Note that stages could be defined to be of varying length.
Myopic0 = perfect foresight, 1 = myopic model (see above table)
ConvergenceToleranceThe relative optimality gap used for convergence of the dual dynamic programming algorithm. Only required when Myopic = 0
WACCRate used to discount non-technology-specific costs from stage to stage (i.e., the “social discount rate”).
time_domain_reduction_settings.yml
MultiStageConcatenateDesignates whether to use time domain reduction for the full set of input data together (1) or to reduce only the first stage data and apply the returned representative periods to the rest of the input data (0).
diff --git a/previews/PR655/User_Guide/running_TDR/index.html b/previews/PR655/User_Guide/running_TDR/index.html index 8803d5aafe..83ecd80a82 100644 --- a/previews/PR655/User_Guide/running_TDR/index.html +++ b/previews/PR655/User_Guide/running_TDR/index.html @@ -6,4 +6,4 @@ 2184.0,

In this example, the first week represents a total of 26*168 = 4368 hours over a full year.

The time series data are written in single unbroken columns: in this example, the Time_Index ranges from 1 to 504.

For problems involving Long Duration Storage, a file Period_map.csv is necessary to describe how these representative periods occur throughout the modeled year.

See also the Time-domain reduction.

Performing time domain reduction (TDR) separately from optimization

Added in 0.3.4

It may be useful to perform time domain reduction (TDR) (or "clustering") on a set of inputs before using them as part of full GenX optimization task. For example, a user might want to test various TDR settings and examine the resulting clustered inputs. This can now be performed using the run_timedomainreduction! function.

$ julia --project=/home/youruser/GenX
 
 julia> using GenX
-julia> run_timedomainreduction!("/path/to/case")

This function will obey the settings in path/to/case/settings/time_domain_reduction_settings.yml. It will output the resulting clustered time series files in the case.

Running this function will overwrite these files in the case. This is done with the expectation that the user is trying out various settings.

+julia> run_timedomainreduction!("/path/to/case")

This function will obey the settings in path/to/case/settings/time_domain_reduction_settings.yml. It will output the resulting clustered time series files in the case.

Running this function will overwrite these files in the case. This is done with the expectation that the user is trying out various settings.

diff --git a/previews/PR655/User_Guide/running_model/index.html b/previews/PR655/User_Guide/running_model/index.html index d9ca29cbc0..fb0a590d57 100644 --- a/previews/PR655/User_Guide/running_model/index.html +++ b/previews/PR655/User_Guide/running_model/index.html @@ -3,4 +3,4 @@ julia> using GenX julia> run_genx_case!("/path/to/case")

where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case.

Alternatively, you can create a Run.jl file with the following code:

using GenX
-run_genx_case!(dirname(@__FILE__))

and and place it in the case folder. Then, you can run the case by opening a terminal and running the following command:

$ julia --project="/path/to/GenX" /path/to/case/Run.jl

where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case.

The output files will be saved in the Results folder inside the case folder. Check out the GenX Outputs section for more information on the output files.

Slack Variables

To run a case with slack variables, check out the Policy Slack Variables section.

+run_genx_case!(dirname(@__FILE__))

and and place it in the case folder. Then, you can run the case by opening a terminal and running the following command:

$ julia --project="/path/to/GenX" /path/to/case/Run.jl

where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case.

The output files will be saved in the Results folder inside the case folder. Check out the GenX Outputs section for more information on the output files.

Slack Variables

To run a case with slack variables, check out the Policy Slack Variables section.

diff --git a/previews/PR655/User_Guide/slack_variables_overview/index.html b/previews/PR655/User_Guide/slack_variables_overview/index.html index 586baa132a..06545043d2 100644 --- a/previews/PR655/User_Guide/slack_variables_overview/index.html +++ b/previews/PR655/User_Guide/slack_variables_overview/index.html @@ -1,2 +1,2 @@ -Slack Variables for Policies · GenX

Policy Slack Variables

Added in 0.3.5

Rather than modeling policy requirements as inflexible constraints, it may be advantageous to instead allow these requirements to be violated at some predetermined cost. This is accomplished via 'slack variables,' which can be used by the model to meet a policy constraint if it cannot be met cost-effectively by normal means. Once the incremental shadow price of meeting a policy constraint rises above a cost threshold set by the user, the model will rely on the slack variable to fill any remaining gap.

Using slack variables rather than hard constraints may be useful for GenX users who wish to avoid unexpected infeasibilities resulting from policy requirements that cannot be met. Using slack variables with very high cost thresholds, users can quickly identify specific policy constraints that are effectively infeasible without causing errors.

Slack variables with lower assigned costs can also be used to model policies with built-in cost thresholds, for example a CO2 Cap with a maximum allowable carbon price of $200/ton. They can be activated for each individual policy type available in GenX, including: Capacity Reserve Margins, Energy Share Requirements, CO2 Caps, Minimum Capacity Requirements, and Maximum Capacity Requirements.

Running cases with slack variables

Slack variables are turned off by default in GenX, but can be automatically activated for each policy type by providing the relevant inputs. Slack variables will only be activated when the relevant policy type is itself activated in GenX_settings.yml. For some policy types, slack variables are activated by providing a new input file, while for others they are activated by modifying an existing file. Instructions for each policy type are listed below:

Capacity Reserve Margin

Slack variables for Capacity Reserve Margin constraints are created when GenX detects the presence of the file Capacity_reserve_margin_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CRMConstraint' naming the individual Capacity Reserve Margin constraints in the same order in which they are listed in the first row of `Capacityreserve_margin.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /MW.

CO2 Cap

Slack variables for CO2 Cap constraints are created when GenX detects the presence of the file CO2_cap_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CO2CapConstraint' naming the individual CO2 Cap constraints in the same order in which they are listed in the first row of CO2_Cap.csv, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /ton. The CO2 Cap slack variable itself is always in units of tons of CO2, even if the CO2 Cap is a rate-based cap.

Energy Share Requirement

Slack variables for Energy Share Requirement constraints are created when GenX detects the presence of the file Energy_share_requirement_slack.csv in the Inputs folder. This file should contain two columns: one titled 'ESRConstraint' naming the individual Energy Share Requirement constraints in the same order in which they are listed in the first row of `Energyshare_requirement.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are $/MWh.

Minimum Capacity Requirement

Slack variables for Minimum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Minimum_capacity_requirement.csv. This column contains the price thresholds for each Minimum Capacity Requirement constraint, in units of $/MW.

Maximum Capacity Requirement

Slack variables for Maximum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Maximum_capacity_requirement.csv. This column contains the price thresholds for each Maximum Capacity Requirement constraint, in units of $/MW.

Slack Variables Results Files

By default, a policy type's result files include the shadow prices for each policy constraint. When slack variables are activated, outputs also include the final values of the slack variables (i.e. the amount by which the policy constraint was violated), and the total costs associated with those slack variables. These files are named using the convention X_prices_and_penalties.csv, where X is the name of the relevant policy type.

GenX will also print the total cost associated with each activated slack variable type in the file costs.csv.

Slack Variables Example

The folder Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example contains examples of the input files needed to activate slack variables for each of the policy types in GenX. Running this example with a given set of policy constraints activated will generate the relevant slack variables and print their outputs.

+Slack Variables for Policies · GenX

Policy Slack Variables

Added in 0.3.5

Rather than modeling policy requirements as inflexible constraints, it may be advantageous to instead allow these requirements to be violated at some predetermined cost. This is accomplished via 'slack variables,' which can be used by the model to meet a policy constraint if it cannot be met cost-effectively by normal means. Once the incremental shadow price of meeting a policy constraint rises above a cost threshold set by the user, the model will rely on the slack variable to fill any remaining gap.

Using slack variables rather than hard constraints may be useful for GenX users who wish to avoid unexpected infeasibilities resulting from policy requirements that cannot be met. Using slack variables with very high cost thresholds, users can quickly identify specific policy constraints that are effectively infeasible without causing errors.

Slack variables with lower assigned costs can also be used to model policies with built-in cost thresholds, for example a CO2 Cap with a maximum allowable carbon price of $200/ton. They can be activated for each individual policy type available in GenX, including: Capacity Reserve Margins, Energy Share Requirements, CO2 Caps, Minimum Capacity Requirements, and Maximum Capacity Requirements.

Running cases with slack variables

Slack variables are turned off by default in GenX, but can be automatically activated for each policy type by providing the relevant inputs. Slack variables will only be activated when the relevant policy type is itself activated in GenX_settings.yml. For some policy types, slack variables are activated by providing a new input file, while for others they are activated by modifying an existing file. Instructions for each policy type are listed below:

Capacity Reserve Margin

Slack variables for Capacity Reserve Margin constraints are created when GenX detects the presence of the file Capacity_reserve_margin_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CRMConstraint' naming the individual Capacity Reserve Margin constraints in the same order in which they are listed in the first row of `Capacityreserve_margin.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /MW.

CO2 Cap

Slack variables for CO2 Cap constraints are created when GenX detects the presence of the file CO2_cap_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CO2CapConstraint' naming the individual CO2 Cap constraints in the same order in which they are listed in the first row of CO2_Cap.csv, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /ton. The CO2 Cap slack variable itself is always in units of tons of CO2, even if the CO2 Cap is a rate-based cap.

Energy Share Requirement

Slack variables for Energy Share Requirement constraints are created when GenX detects the presence of the file Energy_share_requirement_slack.csv in the Inputs folder. This file should contain two columns: one titled 'ESRConstraint' naming the individual Energy Share Requirement constraints in the same order in which they are listed in the first row of `Energyshare_requirement.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are $/MWh.

Minimum Capacity Requirement

Slack variables for Minimum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Minimum_capacity_requirement.csv. This column contains the price thresholds for each Minimum Capacity Requirement constraint, in units of $/MW.

Maximum Capacity Requirement

Slack variables for Maximum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Maximum_capacity_requirement.csv. This column contains the price thresholds for each Maximum Capacity Requirement constraint, in units of $/MW.

Slack Variables Results Files

By default, a policy type's result files include the shadow prices for each policy constraint. When slack variables are activated, outputs also include the final values of the slack variables (i.e. the amount by which the policy constraint was violated), and the total costs associated with those slack variables. These files are named using the convention X_prices_and_penalties.csv, where X is the name of the relevant policy type.

GenX will also print the total cost associated with each activated slack variable type in the file costs.csv.

Slack Variables Example

The folder Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example contains examples of the input files needed to activate slack variables for each of the policy types in GenX. Running this example with a given set of policy constraints activated will generate the relevant slack variables and print their outputs.

diff --git a/previews/PR655/User_Guide/solver_configuration/index.html b/previews/PR655/User_Guide/solver_configuration/index.html index 7208bf622e..d6963a7061 100644 --- a/previews/PR655/User_Guide/solver_configuration/index.html +++ b/previews/PR655/User_Guide/solver_configuration/index.html @@ -1,2 +1,2 @@ -Solver Configuration · GenX

Solver Configuration

To define and solve the optimization problems, GenX relies on JuMP, a domain-specific modeling language for mathematical optimization written in Julia, and on a variety of open-source and commercial solvers. GenX supports the following solvers:

Solver related settings parameters are specified in the appropriate .yml file (e.g. highs_settings.yml, gurobi_settings.yml, etc.), which should be located in the settings folder inside the current working directory (the same settings folder where genx_settings.yml is located). Settings are specific to each solver. Check the Example_Systems folder for examples of solver settings files and parameters.

Note

GenX supplies default settings for most solver settings in the various solver-specific functions found in the src/configure_solver/ directory. To overwrite default settings, you can specify the below Solver specific settings.

The following table summarizes the solver settings parameters and their default/possible values.

Tip

Since each solver has its own set of parameters names, together with a description of the parameter, the table provides a reference to the the corresponding solver specific parameter name.

Solver settings parameters**

Settings ParameterDescription
MethodAlgorithm used to solve continuous models or the root node of a MIP model. Generally, barrier method provides the fastest run times for real-world problem set.
CPLEX: CPX_PARAM_LPMETHOD - Default = 0; See link for more specifications.
Gurobi: Method - Default = -1; See link for more specifications.
clp: SolveType - Default = 5; See link for more specifications.
HiGHS: Method - Default = "choose"; See link for more specifications.
BarConvTolConvergence tolerance for barrier algorithm.
CPLEX: CPX_PARAM_BAREPCOMP - Default = 1e-8; See link for more specifications.
Gurobi: BarConvTol - Default = 1e-8; See link for more specifications.
Feasib_TolAll constraints must be satisfied as per this tolerance. Note that this tolerance is absolute.
CPLEX: CPX_PARAM_EPRHS - Default = 1e-6; See link for more specifications.
Gurobi: FeasibilityTol - Default = 1e-6; See link for more specifications.
clp: PrimalTolerance - Default = 1e-7; See link for more specifications.
clp: DualTolerance - Default = 1e-7; See link for more specifications.
Optimal_TolReduced costs must all be smaller than Optimal_Tol in the improving direction in order for a model to be declared optimal.
CPLEX: CPX_PARAM_EPOPT - Default = 1e-6; See link for more specifications.
Gurobi: OptimalityTol - Default = 1e-6; See link for more specifications.
Pre_SolveControls the presolve level.
Gurobi: Presolve - Default = -1; See link for more specifications.
clp: PresolveType - Default = 5; See link for more specifications.
CrossoverDetermines the crossover strategy used to transform the interior solution produced by barrier algorithm into a basic solution.
CPLEX: CPX_PARAM_SOLUTIONTYPE - Default = 2; See link for more specifications.
Gurobi: Crossover - Default = 0; See link for more specifications.
NumericFocusControls the degree to which the code attempts to detect and manage numerical issues.
CPLEX: CPX_PARAM_NUMERICALEMPHASIS - Default = 0; See link for more specifications.
Gurobi: NumericFocus - Default = 0; See link for more specifications.
TimeLimitTime limit to terminate the solution algorithm, model could also terminate if it reaches MIPGap before this time.
CPLEX: CPX_PARAM_TILIM- Default = 1e+75; See link for more specifications.
Gurobi: TimeLimit - Default = infinity; See link for more specifications.
clp: MaximumSeconds - Default = -1; See link for more specifications.
MIPGapOptimality gap in case of mixed-integer program.
CPLEX: CPX_PARAM_EPGAP- Default = 1e-4; See link for more specifications.
Gurobi: MIPGap - Default = 1e-4; See link for more specifications.
DualObjectiveLimitWhen using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit.
clp: DualObjectiveLimit - Default = 1e308; See link for more specifications.
MaximumIterationsTerminate after performing this number of simplex iterations.
clp: MaximumIterations - Default = 2147483647; See link for more specifications.
LogLevelSet to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output.
clp: logLevel - Default = 1; See link for more specifications.
cbc: logLevel - Default = 1; See link for more specifications.
InfeasibleReturnSet to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well).
clp: InfeasibleReturn - Default = 0; See link for more specifications.
ScalingSets or unsets scaling; 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic(later).
clp: Scaling - Default = 3; See link for more specifications.
PerturbationPerturbs problem; Switch on perturbation (50), automatic (100), don't try perturbing (102).
clp: Perturbation - Default = 3; See link for more specifications.
maxSolutionsTerminate after this many feasible solutions have been found.
cbc: maxSolutions - Default = -1; See link for more specifications.
maxNodesTerminate after this many branch-and-bound nodes have been evaluated
cbc: maxNodes - Default = -1; See link for more specifications.
allowableGapTerminate after optimality gap is less than this value (on an absolute scale)
cbc: allowableGap - Default = -1; See link for more specifications.
ratioGapTerminate after optimality gap is smaller than this relative fraction.
cbc: ratioGap - Default = Inf; See link for more specifications.
threadsSet the number of threads to use for parallel branch & bound.
cbc: threads - Default = 1; See link for more specifications.
+Solver Configuration · GenX

Solver Configuration

To define and solve the optimization problems, GenX relies on JuMP, a domain-specific modeling language for mathematical optimization written in Julia, and on a variety of open-source and commercial solvers. GenX supports the following solvers:

Solver related settings parameters are specified in the appropriate .yml file (e.g. highs_settings.yml, gurobi_settings.yml, etc.), which should be located in the settings folder inside the current working directory (the same settings folder where genx_settings.yml is located). Settings are specific to each solver. Check the Example_Systems folder for examples of solver settings files and parameters.

Note

GenX supplies default settings for most solver settings in the various solver-specific functions found in the src/configure_solver/ directory. To overwrite default settings, you can specify the below Solver specific settings.

The following table summarizes the solver settings parameters and their default/possible values.

Tip

Since each solver has its own set of parameters names, together with a description of the parameter, the table provides a reference to the the corresponding solver specific parameter name.

Solver settings parameters**

Settings ParameterDescription
MethodAlgorithm used to solve continuous models or the root node of a MIP model. Generally, barrier method provides the fastest run times for real-world problem set.
CPLEX: CPX_PARAM_LPMETHOD - Default = 0; See link for more specifications.
Gurobi: Method - Default = -1; See link for more specifications.
clp: SolveType - Default = 5; See link for more specifications.
HiGHS: Method - Default = "choose"; See link for more specifications.
BarConvTolConvergence tolerance for barrier algorithm.
CPLEX: CPX_PARAM_BAREPCOMP - Default = 1e-8; See link for more specifications.
Gurobi: BarConvTol - Default = 1e-8; See link for more specifications.
Feasib_TolAll constraints must be satisfied as per this tolerance. Note that this tolerance is absolute.
CPLEX: CPX_PARAM_EPRHS - Default = 1e-6; See link for more specifications.
Gurobi: FeasibilityTol - Default = 1e-6; See link for more specifications.
clp: PrimalTolerance - Default = 1e-7; See link for more specifications.
clp: DualTolerance - Default = 1e-7; See link for more specifications.
Optimal_TolReduced costs must all be smaller than Optimal_Tol in the improving direction in order for a model to be declared optimal.
CPLEX: CPX_PARAM_EPOPT - Default = 1e-6; See link for more specifications.
Gurobi: OptimalityTol - Default = 1e-6; See link for more specifications.
Pre_SolveControls the presolve level.
Gurobi: Presolve - Default = -1; See link for more specifications.
clp: PresolveType - Default = 5; See link for more specifications.
CrossoverDetermines the crossover strategy used to transform the interior solution produced by barrier algorithm into a basic solution.
CPLEX: CPX_PARAM_SOLUTIONTYPE - Default = 2; See link for more specifications.
Gurobi: Crossover - Default = 0; See link for more specifications.
NumericFocusControls the degree to which the code attempts to detect and manage numerical issues.
CPLEX: CPX_PARAM_NUMERICALEMPHASIS - Default = 0; See link for more specifications.
Gurobi: NumericFocus - Default = 0; See link for more specifications.
TimeLimitTime limit to terminate the solution algorithm, model could also terminate if it reaches MIPGap before this time.
CPLEX: CPX_PARAM_TILIM- Default = 1e+75; See link for more specifications.
Gurobi: TimeLimit - Default = infinity; See link for more specifications.
clp: MaximumSeconds - Default = -1; See link for more specifications.
MIPGapOptimality gap in case of mixed-integer program.
CPLEX: CPX_PARAM_EPGAP- Default = 1e-4; See link for more specifications.
Gurobi: MIPGap - Default = 1e-4; See link for more specifications.
DualObjectiveLimitWhen using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit.
clp: DualObjectiveLimit - Default = 1e308; See link for more specifications.
MaximumIterationsTerminate after performing this number of simplex iterations.
clp: MaximumIterations - Default = 2147483647; See link for more specifications.
LogLevelSet to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output.
clp: logLevel - Default = 1; See link for more specifications.
cbc: logLevel - Default = 1; See link for more specifications.
InfeasibleReturnSet to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well).
clp: InfeasibleReturn - Default = 0; See link for more specifications.
ScalingSets or unsets scaling; 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic(later).
clp: Scaling - Default = 3; See link for more specifications.
PerturbationPerturbs problem; Switch on perturbation (50), automatic (100), don't try perturbing (102).
clp: Perturbation - Default = 3; See link for more specifications.
maxSolutionsTerminate after this many feasible solutions have been found.
cbc: maxSolutions - Default = -1; See link for more specifications.
maxNodesTerminate after this many branch-and-bound nodes have been evaluated
cbc: maxNodes - Default = -1; See link for more specifications.
allowableGapTerminate after optimality gap is less than this value (on an absolute scale)
cbc: allowableGap - Default = -1; See link for more specifications.
ratioGapTerminate after optimality gap is smaller than this relative fraction.
cbc: ratioGap - Default = Inf; See link for more specifications.
threadsSet the number of threads to use for parallel branch & bound.
cbc: threads - Default = 1; See link for more specifications.
diff --git a/previews/PR655/User_Guide/workflow/index.html b/previews/PR655/User_Guide/workflow/index.html index c8af4d6123..b94e4e291b 100644 --- a/previews/PR655/User_Guide/workflow/index.html +++ b/previews/PR655/User_Guide/workflow/index.html @@ -5,4 +5,4 @@ println("Time elapsed for model building is") println(time_elapsed)

The above function call instantiates the different decision variables, constraints, and objective function expressions from the input data. It can be seen that we also keep track of the time required to build the model. Follwoing this, the solve_model function makes the call to the solver and return the results as well as the solve time.

EP, solve_time = solve_model(EP, mysetup)
 myinputs["solve_time"] = solve_time # Store the model solve time in myinputs

For writing the results, we invoke the following function:

outputs_path = get_default_output_folder(case)
-elapsed_time = @elapsed outputs_path = write_outputs(EP, outputs_path, mysetup, myinputs)

The call to the writeoutputs() function in turn calls a series of functions (writecapacity, write_power etc.) each of which querries the respective decision variables and creates dataframes, eventually outputting the results to separate CSV files.

Single and Multi-stage investment planning

In addition to the standard single-stage planning mode, in which the produces a single snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions, recent improvements in the GenX source code (part of v0.3 release) enable its use for studying long-term evolution of the power system across multiple investment stages. GenX can be used to study multi-stage power system planning in the following two ways:

+elapsed_time = @elapsed outputs_path = write_outputs(EP, outputs_path, mysetup, myinputs)

The call to the writeoutputs() function in turn calls a series of functions (writecapacity, write_power etc.) each of which querries the respective decision variables and creates dataframes, eventually outputting the results to separate CSV files.

Single and Multi-stage investment planning

In addition to the standard single-stage planning mode, in which the produces a single snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions, recent improvements in the GenX source code (part of v0.3 release) enable its use for studying long-term evolution of the power system across multiple investment stages. GenX can be used to study multi-stage power system planning in the following two ways:

diff --git a/previews/PR655/additional_third_party_extensions/index.html b/previews/PR655/additional_third_party_extensions/index.html index 0d259fec13..6b34cd0160 100644 --- a/previews/PR655/additional_third_party_extensions/index.html +++ b/previews/PR655/additional_third_party_extensions/index.html @@ -1,2 +1,2 @@ -Third Party Extensions · GenX

Additional Third Party Extensions to GenX

pygenx: Python interface for GenX

Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation.

Simple GenX Case Runner: For automated sequential batch run for GenX

It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner

+Third Party Extensions · GenX

Additional Third Party Extensions to GenX

pygenx: Python interface for GenX

Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation.

Simple GenX Case Runner: For automated sequential batch run for GenX

It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner

diff --git a/previews/PR655/developer_guide/index.html b/previews/PR655/developer_guide/index.html index 9eef2b23df..5cfbfdfa32 100644 --- a/previews/PR655/developer_guide/index.html +++ b/previews/PR655/developer_guide/index.html @@ -62,7 +62,7 @@ 0

Example:

julia> haskey(thermal_gen[1], :existing_cap_mw)
 true
 julia> haskey(thermal_gen[1], :new_build)
-false

Example:

julia> findall(r -> isa(r,Thermal), thermal_gen) # returns the indices of the thermal resources in thermal_gen
+false

Example:

julia> findall(r -> isa(r,Thermal), thermal_gen) # returns the indices of the thermal resources in thermal_gen
 3-element Vector{Int64}:
  23
  24
@@ -133,4 +133,4 @@
 attribute_1 (generic function with 1 method)

And then:

julia> attribute_1(new_res1)
 6.2
 julia> new_res1.attribute_1
-6.2

Utility functions to work with JuMP expressions in GenX

GenX.add_similar_to_expression!Method
add_similar_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dim1}, expr2::AbstractArray{V, dim2}) where {C,T,V,dim1,dim2}

Add an array of some type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr). However, the accessed parts of both arrays must have the same dimensions.

source
GenX.add_term_to_expression!Method
add_term_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dims}, expr2::V) where {C,T,V,dims}

Add an entry of type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr).

source
GenX.check_addable_to_exprMethod
check_addable_to_expr(C::DataType, T::DataType)

Check that two datatype can be added using addtoexpression!(). Raises an error if not.

This needs some work to make it more flexible. Right now it's challenging to use with GenericAffExpr{C,T} as the method only works on the constituent types making up the GenericAffExpr, not the resulting expression type. Also, the default MethodError from addtoexpression! is sometime more informative than the error message here.

source
GenX.check_sizes_matchMethod
check_sizes_match(expr1::AbstractArray{C, dim1}, expr2::AbstractArray{T, dim2}) where {C,T,dim1, dim2}

Check that two arrays have the same dimensions. If not, return an error message which includes the dimensions of both arrays.

source
GenX.create_empty_expression!Method
create_empty_expression!(EP::Model, exprname::Symbol, dims::NTuple{N, Int64}) where N

Create an dense array filled with zeros which can be altered later. Other approaches to creating zero-filled arrays will often return an array of floats, not expressions. This can lead to errors later if a method can only operate on expressions.

We don't currently have a method to do this with non-contiguous indexing.

source
GenX.fill_with_const!Method
fill_with_const!(arr::AbstractArray{GenericAffExpr{C,T}, dims}, con::Real) where {C,T,dims}

Fill an array of expressions with the specified constant, in-place.

In the future we could expand this to non AffExpr, using GenericAffExpr e.g. if we wanted to use Float32 instead of Float64

source
GenX.fill_with_zeros!Method
fill_with_zeros!(arr::AbstractArray{GenericAffExpr{C,T}, dims}) where {C,T,dims}

Fill an array of expressions with zeros in-place.

source
GenX.sum_expressionMethod
sum_expression(expr::AbstractArray{C, dims}) where {C,dims} :: C

Sum an array of expressions into a single expression and return the result. We're using errors from addtoexpression!() to check that the types are compatible.

source
+6.2

Utility functions to work with JuMP expressions in GenX

GenX.add_similar_to_expression!Method
add_similar_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dim1}, expr2::AbstractArray{V, dim2}) where {C,T,V,dim1,dim2}

Add an array of some type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr). However, the accessed parts of both arrays must have the same dimensions.

source
GenX.add_term_to_expression!Method
add_term_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dims}, expr2::V) where {C,T,V,dims}

Add an entry of type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr).

source
GenX.check_addable_to_exprMethod
check_addable_to_expr(C::DataType, T::DataType)

Check that two datatype can be added using addtoexpression!(). Raises an error if not.

This needs some work to make it more flexible. Right now it's challenging to use with GenericAffExpr{C,T} as the method only works on the constituent types making up the GenericAffExpr, not the resulting expression type. Also, the default MethodError from addtoexpression! is sometime more informative than the error message here.

source
GenX.check_sizes_matchMethod
check_sizes_match(expr1::AbstractArray{C, dim1}, expr2::AbstractArray{T, dim2}) where {C,T,dim1, dim2}

Check that two arrays have the same dimensions. If not, return an error message which includes the dimensions of both arrays.

source
GenX.create_empty_expression!Method
create_empty_expression!(EP::Model, exprname::Symbol, dims::NTuple{N, Int64}) where N

Create an dense array filled with zeros which can be altered later. Other approaches to creating zero-filled arrays will often return an array of floats, not expressions. This can lead to errors later if a method can only operate on expressions.

We don't currently have a method to do this with non-contiguous indexing.

source
GenX.fill_with_const!Method
fill_with_const!(arr::AbstractArray{GenericAffExpr{C,T}, dims}, con::Real) where {C,T,dims}

Fill an array of expressions with the specified constant, in-place.

In the future we could expand this to non AffExpr, using GenericAffExpr e.g. if we wanted to use Float32 instead of Float64

source
GenX.fill_with_zeros!Method
fill_with_zeros!(arr::AbstractArray{GenericAffExpr{C,T}, dims}) where {C,T,dims}

Fill an array of expressions with zeros in-place.

source
GenX.sum_expressionMethod
sum_expression(expr::AbstractArray{C, dims}) where {C,dims} :: C

Sum an array of expressions into a single expression and return the result. We're using errors from addtoexpression!() to check that the types are compatible.

source
diff --git a/previews/PR655/index.html b/previews/PR655/index.html index 62db7202d5..549d335fbd 100644 --- a/previews/PR655/index.html +++ b/previews/PR655/index.html @@ -1,3 +1,3 @@ GenX: Introduction · GenX
-

Welcome to the GenX documentation!

What is GenX?

GenX is a highly-configurable, open source electricity resource capacity expansion model that incorporates several state-of-the-art practices in electricity system planning to offer improved decision support for a changing electricity landscape.

The model was originally developed by Jesse D. Jenkins and Nestor A. Sepulveda at the Massachusetts Institute of Technology and is now jointly maintained by a team of contributors at the Princeton University ZERO Lab (led by Jenkins), MIT (led by Ruaridh MacDonald), and NYU (led by Dharik Mallapragada).

GenX is a constrained linear or mixed integer linear optimization model that determines the portfolio of electricity generation, storage, transmission, and demand-side resource investments and operational decisions to meet electricity demand in one or more future planning years at lowest cost, while subject to a variety of power system operational constraints, resource availability limits, and other imposed environmental, market design, and policy constraints.

GenX features a modular and transparent code structure developed in Julia + JuMP. The model is designed to be highly flexible and configurable for use in a variety of applications from academic research and technology evaluation to public policy and regulatory analysis and resource planning. See the User Guide for more information on how to use GenX and the Developer Guide for more information on how to contribute to GenX.

Uses

From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.

Roadmap of the Documentation: A Guide for the Users and Developers

This section provides a quick guidance as to how to navigate through the different parts of the documentation pages; what the different sections contain, and how to relate it to the different parts of the GenX code-base.

This page serves as a gentle introduction to what GenX is meant for and what it does.

The next subsection, Installation Guide goes over how to download and install GenX and also how to download and install the Julia programming language (in which GenX is written) and the different open-source non-commercial freely available solvers, as well as the commercial solvers and the respective JuMP interfaces. This subsection also goes over installing the environment dependencies and instantiating a virtual environment.

We also mention the shortcomings of GenX and some third party extentions in the next couple subsections

The next section is Getting Started goes over Running GenX and has two subsections. The first subsection, Example cases, gives a walkthrough through some predefined example systems and how to run GenX for those and interpret the results. It also tells how to run GenX for a user-defined case. The subsection Using commercial solvers: Gurobi or CPLEX talks specifically about how to run GenX with commercial solvers like Gurobi and CPLEX that are absolutely indispensable for solving large cases.

The third section, Tutorial starts with GenX Tutorials and gives a comprehensive tour of the different steps that are involved when a GenX capacity expansion simulation is run. It consists of 6 tutorial sections, each of which highlights the different important aspects of model construction and run of GenX. The different sections are configuring the GenX settings, visualizing the network, time domain reduction, generating the model, solving the model, and adjusting the different solver settings.

The User Guide, which the fourth section (User Guide) goes into the depths and details of the different steps and the settings and input parameters from the previous Tutorial section. The sections starts off with an overview of the workflow in GenX, briefing about the different steps (some of which we encountered in the Tutorials) of running GenX model. It then explains the different parameters of settings, policy, time-domain reduction, model structure, and output. Following this, the next subsection explains the different solver settings parameters of the different solvers. The next subsection goes over the different input CSV files and the different fields that are used there. The following two subsections are devoted to Time Domain Reduction (TDR). The first one walks through and explains the different settings parameters for TDR and the second one explains the couple different ways to run TDR for GenX and what exactly happens when we run TDR. The next four subsections, respectively, explains the different parameters, inputs, and outputs, and what happens when Modeling to Generate Alternatives (MGA), Multi-stage model, slack variables for policies (when we want to satisfy policy constraints in a soft manner by adding penalty of violation in the objective function), and Method of Morris. Finally, the last two sections are about the different steps involved while solving the model and the explanation of different output fields for both the default settings and user-specific settings.

The Model Concept and Overview section first introduces the GenX model in GenX Model Introduction and talks about its scope. It also introduces the notations, the objective function, and the power balance constraints. This is the first section which delves into the theoretical and mathematical details of the model, which is the most important one for model developers.

The Model Reference, which is the sixth section delves deep into the GenX model and introduces the mathematical formulation, while discussing the physical interpretations of all the different parts of the GenX model. This section starts off with discussing the Core of the model, which models the Discharge, Non-Served Energy, Operational Reserves, Transmission, Unit Commitment, CO2, and Fuel. The different parts of the model consists of the different tyoe of generating resources (thermal, hydro, VRE, storage etc.), transmission network (modeling of flows as well as losses), demand modeling, operating reserves, unit commitment, different policies (such as CO2 constraint, capacity reserve margin, energy share requirement, min and max cap requirement etc.). This section also mentions about the different Julia functions (or methods) used for loading the input files, building the model, solving it, and generating the output files. Also, this is the section that explains the internal details of the Julia functions used for TDR, MGA, Method of Morris, Multi-stage modeling, and the several utility functions used throughout the GenX code-base.

The seventh section, Public API Reference Public Documentation is for describing the functions that are directly accessible to an external program from GenX (like loading inputs, generating output, running TDR script etc.) and how an external "client" code can access the GenX features, if the user desires to run his/her own code instead of the Run.jl provided by us.

The eighth section, Third Party Extension Additional Third Party Extensions to GenX mentions about Pygenx, a Python interface for GenX, that was built by Daniel Olsen and GenX case runner for automated batch running, built by Jacob Schwartz.

Finally, the ninth and last section, Developer Docs How to contribute to GenX talks about the resource organization in GenX, how to add a new user-defined resource, and also several JuMP functions that are used as utility throughout the GenX code-base.

How to cite GenX

We recommend users of GenX to cite it in their academic publications and patent filings. Here's the text to put up as the citation for GenX: MIT Energy Initiative and Princeton University ZERO lab. [GenX](https://github.com/GenXProject/GenX): a configurable power system capacity expansion model for studying low-carbon energy futures n.d. https://github.com/GenXProject/GenX.

Acknowledgement

The GenX team expresses deep gratitude to Laura Zwanziger and Jacob Schwartz for designing the Julia-themed GenX logo and to Maya Mutic for developing the tutorials along with Filippo Pecci and Luca Bonaldo.

License

GenX is released under the General Public License, GPL-2.0

Index

+

Welcome to the GenX documentation!

What is GenX?

GenX is a highly-configurable, open source electricity resource capacity expansion model that incorporates several state-of-the-art practices in electricity system planning to offer improved decision support for a changing electricity landscape.

The model was originally developed by Jesse D. Jenkins and Nestor A. Sepulveda at the Massachusetts Institute of Technology and is now jointly maintained by a team of contributors at the Princeton University ZERO Lab (led by Jenkins), MIT (led by Ruaridh MacDonald), and NYU (led by Dharik Mallapragada).

GenX is a constrained linear or mixed integer linear optimization model that determines the portfolio of electricity generation, storage, transmission, and demand-side resource investments and operational decisions to meet electricity demand in one or more future planning years at lowest cost, while subject to a variety of power system operational constraints, resource availability limits, and other imposed environmental, market design, and policy constraints.

GenX features a modular and transparent code structure developed in Julia + JuMP. The model is designed to be highly flexible and configurable for use in a variety of applications from academic research and technology evaluation to public policy and regulatory analysis and resource planning. See the User Guide for more information on how to use GenX and the Developer Guide for more information on how to contribute to GenX.

Uses

From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.

Roadmap of the Documentation: A Guide for the Users and Developers

This section provides a quick guidance as to how to navigate through the different parts of the documentation pages; what the different sections contain, and how to relate it to the different parts of the GenX code-base.

This page serves as a gentle introduction to what GenX is meant for and what it does.

The next subsection, Installation Guide goes over how to download and install GenX and also how to download and install the Julia programming language (in which GenX is written) and the different open-source non-commercial freely available solvers, as well as the commercial solvers and the respective JuMP interfaces. This subsection also goes over installing the environment dependencies and instantiating a virtual environment.

We also mention the shortcomings of GenX and some third party extentions in the next couple subsections

The next section is Getting Started goes over Running GenX and has two subsections. The first subsection, Example cases, gives a walkthrough through some predefined example systems and how to run GenX for those and interpret the results. It also tells how to run GenX for a user-defined case. The subsection Using commercial solvers: Gurobi or CPLEX talks specifically about how to run GenX with commercial solvers like Gurobi and CPLEX that are absolutely indispensable for solving large cases.

The third section, Tutorial starts with GenX Tutorials and gives a comprehensive tour of the different steps that are involved when a GenX capacity expansion simulation is run. It consists of 6 tutorial sections, each of which highlights the different important aspects of model construction and run of GenX. The different sections are configuring the GenX settings, visualizing the network, time domain reduction, generating the model, solving the model, and adjusting the different solver settings.

The User Guide, which the fourth section (User Guide) goes into the depths and details of the different steps and the settings and input parameters from the previous Tutorial section. The sections starts off with an overview of the workflow in GenX, briefing about the different steps (some of which we encountered in the Tutorials) of running GenX model. It then explains the different parameters of settings, policy, time-domain reduction, model structure, and output. Following this, the next subsection explains the different solver settings parameters of the different solvers. The next subsection goes over the different input CSV files and the different fields that are used there. The following two subsections are devoted to Time Domain Reduction (TDR). The first one walks through and explains the different settings parameters for TDR and the second one explains the couple different ways to run TDR for GenX and what exactly happens when we run TDR. The next four subsections, respectively, explains the different parameters, inputs, and outputs, and what happens when Modeling to Generate Alternatives (MGA), Multi-stage model, slack variables for policies (when we want to satisfy policy constraints in a soft manner by adding penalty of violation in the objective function), and Method of Morris. Finally, the last two sections are about the different steps involved while solving the model and the explanation of different output fields for both the default settings and user-specific settings.

The Model Concept and Overview section first introduces the GenX model in GenX Model Introduction and talks about its scope. It also introduces the notations, the objective function, and the power balance constraints. This is the first section which delves into the theoretical and mathematical details of the model, which is the most important one for model developers.

The Model Reference, which is the sixth section delves deep into the GenX model and introduces the mathematical formulation, while discussing the physical interpretations of all the different parts of the GenX model. This section starts off with discussing the Core of the model, which models the Discharge, Non-Served Energy, Operational Reserves, Transmission, Unit Commitment, CO2, and Fuel. The different parts of the model consists of the different tyoe of generating resources (thermal, hydro, VRE, storage etc.), transmission network (modeling of flows as well as losses), demand modeling, operating reserves, unit commitment, different policies (such as CO2 constraint, capacity reserve margin, energy share requirement, min and max cap requirement etc.). This section also mentions about the different Julia functions (or methods) used for loading the input files, building the model, solving it, and generating the output files. Also, this is the section that explains the internal details of the Julia functions used for TDR, MGA, Method of Morris, Multi-stage modeling, and the several utility functions used throughout the GenX code-base.

The seventh section, Public API Reference Public Documentation is for describing the functions that are directly accessible to an external program from GenX (like loading inputs, generating output, running TDR script etc.) and how an external "client" code can access the GenX features, if the user desires to run his/her own code instead of the Run.jl provided by us.

The eighth section, Third Party Extension Additional Third Party Extensions to GenX mentions about Pygenx, a Python interface for GenX, that was built by Daniel Olsen and GenX case runner for automated batch running, built by Jacob Schwartz.

Finally, the ninth and last section, Developer Docs How to contribute to GenX talks about the resource organization in GenX, how to add a new user-defined resource, and also several JuMP functions that are used as utility throughout the GenX code-base.

How to cite GenX

We recommend users of GenX to cite it in their academic publications and patent filings. Here's the text to put up as the citation for GenX: MIT Energy Initiative and Princeton University ZERO lab. [GenX](https://github.com/GenXProject/GenX): a configurable power system capacity expansion model for studying low-carbon energy futures n.d. https://github.com/GenXProject/GenX.

Acknowledgement

The GenX team expresses deep gratitude to Laura Zwanziger and Jacob Schwartz for designing the Julia-themed GenX logo and to Maya Mutic for developing the tutorials along with Filippo Pecci and Luca Bonaldo.

License

GenX is released under the General Public License, GPL-2.0

Index

diff --git a/previews/PR655/installation/index.html b/previews/PR655/installation/index.html index 79ad05195d..cf55c3fc6e 100644 --- a/previews/PR655/installation/index.html +++ b/previews/PR655/installation/index.html @@ -1,2 +1,2 @@ -Installation Guide · GenX

Installation Guide

This guide will walk you through the steps to install Julia, the GenX package, and the required dependencies to run GenX.

Installing Julia

GenX currently exists in version 0.4.0 and runs only on Julia v1.6.x, 1.7.x, 1.8.x, and 1.9.x, where x>=0 and a minimum version of JuMP v1.1.1. To install Julia, please follow the instructions on the Julia website.

Note

We recommend the users to stick to a particular version of Julia to run GenX. If however, the users decide to switch between versions, it's very important to delete the old Manifest.toml file and do a fresh build of GenX.

Downloading GenX and installing dependencies

After installing Julia, you can download GenX by either cloning the repository or downloading the zip file from the GenX GitHub page. For this tutorial it will be assumed to be within your home directory: /home/youruser/GenX. Once you have downloaded GenX, you can install the dependencies by following the steps below:

1. Start a terminal and navigate into the GenX folder.

2. Type julia --project=. to start an instance of the julia kernel with the project set to the current folder. The flag --project=. indicates that Julia will activate the project environment using the Project.toml present in the current folder, .. If running on Windows, the location of Julia can also be specified as e.g., C:\julia-1.6.0\bin\julia.exe --project=..

Tip

The file Project.toml in the parent directory lists all of the dependencies and their versions needed to run GenX. You can see all of the packages installed in your Julia environment and their version numbers by running pkg> status or pkg> st on the package manager command line in the Jula REPL (for more information on the Julia package manager, read the documentation for the Pkg.jl or for the Julia standard library).

Tip

julia --project is a shortcut for julia --project=.

3. Type ] to bring up the package system (GenX) pkg > prompt. This indicates that the GenX project was detected.

Warning

If you see (@v1.6) pkg> as the prompt, then the project was not successfully set.

4. Type instantiate from the (GenX) pkg prompt.

Note for Windows users

On Windows there is an issue with the prepopulated MUMPS_seq_jll v5.5.1 that prevents compilation of the solvers. To avoid this issue type add MUMPS_seq_jll@5.4.1 after running instantiate.

5. Type st to check that the dependecies have been installed. If there is no error, it has been successful.

Tip

Type the back key to come back to the julia> prompt from the package manager.

The above steps are shown in Figure 1 and Figure 2.

Creating the Julia environment and installing dependencies: Steps 2-4 Figure 1. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder.

Creating the Julia environment and installing dependencies: Step 5 Figure 2. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder: Step 5

Installing solvers

GenX requires a solver to be installed to solve the optimization problem. By default, GenX uses one of the following open-source freely available solvers:

  1. HiGHS for linear programming and MILP (default solver)
  2. Clp for linear programming (LP) problems
  3. Cbc for mixed integer linear programming (MILP) problems

We also provide the option to use one of these two commercial solvers:

  1. Gurobi
  2. CPLEX.
Note on commercial solvers

Using Gurobi and CPLEX requires a valid license on the host machine.

Notes on previous versions of GenX

For those users who has previously cloned GenX, and has been running it successfully so far, and therefore might be unwilling to run it on the latest version of Julia: please look into the GitHub branch, old_version.

+Installation Guide · GenX

Installation Guide

This guide will walk you through the steps to install Julia, the GenX package, and the required dependencies to run GenX.

Installing Julia

GenX currently exists in version 0.4.0 and runs only on Julia v1.6.x, 1.7.x, 1.8.x, and 1.9.x, where x>=0 and a minimum version of JuMP v1.1.1. To install Julia, please follow the instructions on the Julia website.

Note

We recommend the users to stick to a particular version of Julia to run GenX. If however, the users decide to switch between versions, it's very important to delete the old Manifest.toml file and do a fresh build of GenX.

Downloading GenX and installing dependencies

After installing Julia, you can download GenX by either cloning the repository or downloading the zip file from the GenX GitHub page. For this tutorial it will be assumed to be within your home directory: /home/youruser/GenX. Once you have downloaded GenX, you can install the dependencies by following the steps below:

1. Start a terminal and navigate into the GenX folder.

2. Type julia --project=. to start an instance of the julia kernel with the project set to the current folder. The flag --project=. indicates that Julia will activate the project environment using the Project.toml present in the current folder, .. If running on Windows, the location of Julia can also be specified as e.g., C:\julia-1.6.0\bin\julia.exe --project=..

Tip

The file Project.toml in the parent directory lists all of the dependencies and their versions needed to run GenX. You can see all of the packages installed in your Julia environment and their version numbers by running pkg> status or pkg> st on the package manager command line in the Jula REPL (for more information on the Julia package manager, read the documentation for the Pkg.jl or for the Julia standard library).

Tip

julia --project is a shortcut for julia --project=.

3. Type ] to bring up the package system (GenX) pkg > prompt. This indicates that the GenX project was detected.

Warning

If you see (@v1.6) pkg> as the prompt, then the project was not successfully set.

4. Type instantiate from the (GenX) pkg prompt.

Note for Windows users

On Windows there is an issue with the prepopulated MUMPS_seq_jll v5.5.1 that prevents compilation of the solvers. To avoid this issue type add MUMPS_seq_jll@5.4.1 after running instantiate.

5. Type st to check that the dependecies have been installed. If there is no error, it has been successful.

Tip

Type the back key to come back to the julia> prompt from the package manager.

The above steps are shown in Figure 1 and Figure 2.

Creating the Julia environment and installing dependencies: Steps 2-4 Figure 1. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder.

Creating the Julia environment and installing dependencies: Step 5 Figure 2. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder: Step 5

Installing solvers

GenX requires a solver to be installed to solve the optimization problem. By default, GenX uses one of the following open-source freely available solvers:

  1. HiGHS for linear programming and MILP (default solver)
  2. Clp for linear programming (LP) problems
  3. Cbc for mixed integer linear programming (MILP) problems

We also provide the option to use one of these two commercial solvers:

  1. Gurobi
  2. CPLEX.
Note on commercial solvers

Using Gurobi and CPLEX requires a valid license on the host machine.

Notes on previous versions of GenX

For those users who has previously cloned GenX, and has been running it successfully so far, and therefore might be unwilling to run it on the latest version of Julia: please look into the GitHub branch, old_version.

diff --git a/previews/PR655/limitations_genx/index.html b/previews/PR655/limitations_genx/index.html index c3f16843b8..ecc0087519 100644 --- a/previews/PR655/limitations_genx/index.html +++ b/previews/PR655/limitations_genx/index.html @@ -1,2 +1,2 @@ -Limitation of GenX · GenX

Limitations of the GenX Model

While the benefits of an openly available generation and transmission expansion model are high, many approximations have been made due to missing data or to manage computational tractability. The assumptions of the GenX model are listed below. It serves as a caveat to the user and as an encouragement to improve the approximations.

1. Time period

GenX makes the simplifying assumption that each time period contains n copies of a single, representative year. GenX optimizes generation and transmission capacity for just this characteristic year within each time period, assuming the results for different years in the same time period are identical. However, the GenX objective function accounts only for the cost of the final model time period.

2. Cost

The GenX objective function assumes that the cost of powerplants is specified in the unit of currency per unit of capacity. GenX also assumes that the capital cost of technologies is paid through loans.

3.Market

GenX is a bottom-up (technology-explicit), partial equilibrium model that assumes perfect markets for commodities. In other words, each commodity is produced such that the sum of producer and consumer surplus is maximized.

4. Technology

Behavioral response and acceptance of new technology are often modeled simplistically as a discount rate or by externally fixing the technology capacity. A higher, technology-specific discount rate represents consumer reluctance to accept newer technologies.

5. Uncertainty

Because each model realization assumes a particular state of the world based on the input values drawn, the parameter uncertainty is propagated through the model in the case of myopic model runs.

6. Decision-making

GenX assumes rational decision making, with perfect information and perfect foresight, and simultaneously optimizes all decisions over the user-specified time horizon.

7. Demand

GenX assumes price-elastic demand segments that are represented using piece-wise approximation rather than an inverse demand curve to keep the model linear.

+Limitation of GenX · GenX

Limitations of the GenX Model

While the benefits of an openly available generation and transmission expansion model are high, many approximations have been made due to missing data or to manage computational tractability. The assumptions of the GenX model are listed below. It serves as a caveat to the user and as an encouragement to improve the approximations.

1. Time period

GenX makes the simplifying assumption that each time period contains n copies of a single, representative year. GenX optimizes generation and transmission capacity for just this characteristic year within each time period, assuming the results for different years in the same time period are identical. However, the GenX objective function accounts only for the cost of the final model time period.

2. Cost

The GenX objective function assumes that the cost of powerplants is specified in the unit of currency per unit of capacity. GenX also assumes that the capital cost of technologies is paid through loans.

3.Market

GenX is a bottom-up (technology-explicit), partial equilibrium model that assumes perfect markets for commodities. In other words, each commodity is produced such that the sum of producer and consumer surplus is maximized.

4. Technology

Behavioral response and acceptance of new technology are often modeled simplistically as a discount rate or by externally fixing the technology capacity. A higher, technology-specific discount rate represents consumer reluctance to accept newer technologies.

5. Uncertainty

Because each model realization assumes a particular state of the world based on the input values drawn, the parameter uncertainty is propagated through the model in the case of myopic model runs.

6. Decision-making

GenX assumes rational decision making, with perfect information and perfect foresight, and simultaneously optimizes all decisions over the user-specified time horizon.

7. Demand

GenX assumes price-elastic demand segments that are represented using piece-wise approximation rather than an inverse demand curve to keep the model linear.

diff --git a/previews/PR655/objects.inv b/previews/PR655/objects.inv index 19e97c8437..7eea8b8c85 100644 Binary files a/previews/PR655/objects.inv and b/previews/PR655/objects.inv differ diff --git a/previews/PR655/search_index.js b/previews/PR655/search_index.js index 9ee10d469e..a16425d3af 100644 --- a/previews/PR655/search_index.js +++ b/previews/PR655/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"Tutorials/Tutorial_5_solve_model/#Tutorial-5:-Solving-the-Model","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In Tutorial 4, we went over how the model is generated when GenX is run using Run.jl. In the function run_genx_case_simple (or multistage), after generate_model is called, solve_model is called to solve the EP.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In this tutorial, we go over how to use JuMP to solve a model, what it looks like to solve GenX, and how to edit the solver settings.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#Table-of-Contents","page":"Tutorial 5: Solving the Model","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"A Simple Example\nGenX\nInfeasibility","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#A-Simple-Example","page":"Tutorial 5: Solving the Model","title":"A Simple Example","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"From Tutorial 4, we have the model:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"beginaligned\n min 10 x + 15 y textObjective function (cost) \n textst \n x + y geq 10 textGrid Demand\n 55x + 70y leq 1000 textConstruction constraint\n 40 x + 5 y leq 200 textEmissions constraint \n x y geq 0 textNon-negativity constraints\nendaligned","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"using JuMP\nusing HiGHS","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"power = Model(HiGHS.Optimizer)\n\n@variable(power,x,Int) # Coal\n@variable(power,y,Int) # Wind\n\n@constraint(power, non_neg_x, x >= 0) # Non-negativity constraint (can't have negative power plants!)\n@constraint(power, non_neg_y, y >= 0) # Non-negativity constraint\n\n@constraint(power, emissions, 40x + 5y <= 200) # Emisisons constraint\n@constraint(power, construction_costs, 55x + 70y <= 1000) # Cost of constructing a new plant\n\n@constraint(power, demand, x + y >= 10) # Grid demand\n\n@expression(power,objective,10x+15y)\n\n@objective(power, Min, objective)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"10 x + 15 y ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"JuMP uses the function optimize!(model) to solve the LP:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"optimize!(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 3 rows, 2 cols, 6 nonzeros\n 3 rows, 2 cols, 6 nonzeros\n Objective function is integral with scale 0.2\n \n Solving MIP model with:\n 3 rows\n 2 cols (0 binary, 2 integer, 0 implied int., 0 continuous)\n 6 nonzeros\n \n Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work \n Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time\n \n 0 0 0 0.00% 90 inf inf 0 0 0 0 0.0s\n \n Solving report\n Status Optimal\n Primal bound 130\n Dual bound 130\n Gap 0% (tolerance: 0.01%)\n Solution status feasible\n 130 (objective)\n 0 (bound viol.)\n 0 (int. viol.)\n 0 (row viol.)\n Timing 0.00 (total)\n 0.00 (presolve)\n 0.00 (postsolve)\n Nodes 1\n LP iterations 1 (total)\n 0 (strong br.)\n 0 (separation)\n 0 (heuristics)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"We can use the function value.() to get the value of each variable, and objective_value() to get the total objective value.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"println(\"# Coal Plants: \", value.(x))\nprintln(\"# Wind Farms: \", value.(y))\nprintln(\"Cost: \", objective_value(power))","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" # Coal Plants: 4.0\n # Wind Farms: 6.0\n Cost: 130.0","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"We can also use the JuMP function solution_summary to see more details of the solution:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"solution_summary(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" * Solver : HiGHS\n \n * Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"kHighsModelStatusOptimal\"\n \n * Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : NO_SOLUTION\n Objective value : 1.30000e+02\n Objective bound : 1.30000e+02\n Relative gap : 0.00000e+00\n \n * Work counters\n Solve time (sec) : 3.36621e-03\n Simplex iterations : 1\n Barrier iterations : -1\n Node count : 1","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#GenX","page":"Tutorial 5: Solving the Model","title":"GenX","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"Let's optimize the GenX model created in the last Tutorial. To do so, we'll create the inputs for generate_model and run it. ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"using GenX","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"case = joinpath(\"example_systems/1_three_zones\") \n\ngenx_settings = GenX.get_settings_path(case, \"genx_settings.yml\");\nwriteoutput_settings = GenX.get_settings_path(case, \"output_settings.yml\")\nsetup = GenX.configure_settings(genx_settings,writeoutput_settings)\n\nsettings_path = GenX.get_settings_path(case)\n\n### Create TDR_Results\nTDRpath = joinpath(case, setup[\"TimeDomainReductionFolder\"])\nsystem_path = joinpath(case, setup[\"SystemFolder\"])\n\nif setup[\"TimeDomainReduction\"] == 1\n GenX.prevent_doubled_timedomainreduction(system_path)\n if !GenX.time_domain_reduced_files_exist(TDRpath)\n println(\"Clustering Time Series Data (Grouped)...\")\n GenX.cluster_inputs(case, settings_path, setup)\n else\n println(\"Time Series Data Already Clustered.\")\n end\nend\n\nOPTIMIZER = GenX.configure_solver(settings_path,HiGHS.Optimizer);\n\ninputs = GenX.load_inputs(setup, case)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"EP = GenX.generate_model(setup,inputs,OPTIMIZER)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 18492\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 5544 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 7398 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 27730 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 2 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 18490 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cCapacityResMargin, cESRShare, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cZoneMaxCapReq, cZoneMinCapReq, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eCapResMarBalance, eCapResMarBalanceStor, eCapResMarBalanceThermal, eCapResMarBalanceVRE, eELOSS, eELOSSByZone, eESR, eESRDischarge, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eMaxCapRes, eMaxCapResInvest, eMinCapRes, eMinCapResInvest, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vZERO","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"The function solve_model(model, setup) uses optimize to optimize the model:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"solution = optimize!(EP) # GenX.solve_model(EP,setup)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"objective_value(EP)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" 9776.57688838726","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#Infeasibility","page":"Tutorial 5: Solving the Model","title":"Infeasibility","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In some cases, your model may not be able to return a value. This happens when no value can be found that satisfies all constraints. To see this, let's go back to our simple example and change one of the parameters to break the model.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"beginaligned\n min 10 x + 15 y textObjective function (cost) \n textst \n x + y geq 10 textGrid Demand\n 55x + 70y leq 1000 textConstruction constraint\n 40 x + 5 y leq 200 textEmissions constraint \n 7 x + 30 y geq 500 textbfNew Constraint \n x y geq 0 textNon-negativity constraints\nendaligned","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"@constraint(power, new, 7x + 30y >= 500)\n","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"7 x + 30 y geq 500 ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"print(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"beginaligned\nminquad 10 x + 15 y\ntextSubject to quad x geq 0\n y geq 0\n x + y geq 10\n 7 x + 30 y geq 500\n 40 x + 5 y leq 200\n 55 x + 70 y leq 1000\n x in mathbbZ\n y in mathbbZ\nendaligned ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"optimize!(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" Presolving model\n Presolve: Infeasible\n \n Solving report\n Status Infeasible\n Primal bound inf\n Dual bound -inf\n Gap inf\n Solution status -\n Timing 0.00 (total)\n 0.00 (presolve)\n 0.00 (postsolve)\n Nodes 0\n LP iterations 0 (total)\n 0 (strong br.)\n 0 (separation)\n 0 (heuristics)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In this case, the infeasibility was detected on the presovle since it's clear no solution would fit within all constraints. For information on how to debug an infeasible solution, see the JuMP documentaion. Some solvers, such as Gurobi, will compute what is causing the conflict, e.g. which constraints are infeasible with one another (HiGHS does not do this). ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"GenX version 0.4 has the feature ComputeConflict in settings. If the model does not work, try setting ComputeConflict = 1, and the conflicting constraints will be returned.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"Tutorial 6 describes the solver settings, how to change them, and the effects of PreSolve, Crossover, and Feasibility Tolerance.","category":"page"},{"location":"Model_Reference/Resources/thermal_no_commit/#Thermal-No-Commit","page":"Thermal No Commit","title":"Thermal No Commit","text":"","category":"section"},{"location":"Model_Reference/Resources/thermal_no_commit/","page":"Thermal No Commit","title":"Thermal No Commit","text":"Modules = [GenX]\nPages = [\"thermal_no_commit.jl\"]","category":"page"},{"location":"Model_Reference/Resources/thermal_no_commit/#GenX.thermal_no_commit!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal No Commit","title":"GenX.thermal_no_commit!","text":"thermal_no_commit!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the operating constraints for thermal power plants NOT subject to unit commitment constraints on power plant start-ups and shut-down decisions (y in H setminus UC).\n\nRamping limits\n\nThermal resources not subject to unit commitment (y in H setminus UC) adhere instead to the following ramping limits on hourly changes in power output:\n\nbeginaligned\n\tTheta_yzt-1 - Theta_yzt leq kappa_yz^down Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt - Theta_yzt-1 leq kappa_yz^up Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 1-2 in the code)\n\nThis set of time-coupling constraints wrap around to ensure the power output in the first time step of each year (or each representative period), t in mathcalT^start, is within the eligible ramp of the power output in the final time step of the year (or each representative period), t+tau^period-1.\n\nMinimum and maximum power output\n\nWhen not modeling regulation and reserves, thermal units not subject to unit commitment decisions are bound by the following limits on maximum and minimum power output:\n\nbeginaligned\n\tTheta_yzt geq rho^min_yz times Delta^total_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt leq rho^max_yzt times Delta^total_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 3-4 in the code)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_no_commit/#GenX.thermal_no_commit_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Thermal No Commit","title":"GenX.thermal_no_commit_operational_reserves!","text":"thermal_no_commit_operational_reserves!(EP::Model, inputs::Dict)\n\nThis function is called by the thermal_no_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants not subject to unit commitment constraints on power plant start-ups and shut-down decisions.\n\nMaximum contributions to frequency regulation and reserves\n\nThermal units not subject to unit commitment adhere instead to the following constraints on maximum reserve and regulation contributions:\n\nbeginaligned\n\tf_yzt leq upsilon^reg_yz times rho^max_yzt Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tr_yzt leq upsilon^rsv_yz times rho^max_yzt Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nwhere f_yzt is the frequency regulation contribution limited by the maximum regulation contribution upsilon^reg_yz, and r_yzt is the reserves contribution limited by the maximum reserves contribution upsilon^rsv_yz. Limits on reserve contributions reflect the maximum ramp rate for the thermal resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nMinimum and maximum power output\n\nWhen modeling regulation and spinning reserves, thermal units not subject to unit commitment are bound by the following limits on maximum and minimum power output:\n\nbeginaligned\n\tTheta_yzt - f_yzt geq rho^min_yz times Delta^texttotal_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt + f_yzt + r_yzt leq rho^max_yzt times Delta^texttotal_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nNote there are multiple versions of these constraints in the code in order to avoid creation of unecessary constraints and decision variables for thermal units unable to provide regulation and/or reserves contributions due to input parameters (e.g. Reg_Max=0 and/or RSV_Max=0).\n\n\n\n\n\n","category":"method"},{"location":"Model_Concept_Overview/model_notation/#Model-Notation","page":"Notation","title":"Model Notation","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/#Model-Indices-and-Sets","page":"Notation","title":"Model Indices and Sets","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"Notation Description\nt in mathcalT where t denotes an time step and mathcalT is the set of time steps over which grid operations are modeled\nmathcalT^interior subseteq mathcalT^ where mathcalT^interior is the set of interior timesteps in the data series\nmathcalT^start subseteq mathcalT where mathcalT^start is the set of initial timesteps in the data series. mathcalT^start=1 when representing entire year as a single contiguous period; mathcalT^start=left(m-1right) times tau^period+1 m in mathcalM, which corresponds to the first time step of each representative period m in mathcalM\nn in mathcalN where n corresponds to a contiguous time period and mathcalN corresponds to the set of contiguous periods of length tau^period that make up the input time series (e.g. demand, variable renewable energy availability) to the model\nmathcalN^rep subseteq mathcalN where mathcalN^rep corresponds to the set of representative time periods that are selected from the set of contiguous periods, mathcalM\nm in mathcalM where m corresponds to a representative time period and mathcalM corresponds to the set of representative time periods indexed as per their chronological ocurrence in the set of contiguous periods spanning the input time series data, i.e. mathcalN\nz in mathcalZ where z denotes a zone and mathcalZ is the set of zones in the network\nl in mathcalL where l denotes a line and mathcalL is the set of transmission lines in the network\ny in mathcalG where y denotes a technology and mathcalG is the set of available technologies\nmathcalH subseteq mathcalG where mathcalH is the subset of thermal resources\nmathcalVRE subseteq mathcalG where mathcalVRE is the subset of curtailable Variable Renewable Energy (VRE) resources\noverlinemathcalVRE^yz set of VRE resource bins for VRE technology type y in mathcalVRE in zone z\nmathcalCE subseteq mathcalG where mathcalCE is the subset of resources qualifying for the clean energy standard policy constraint\nmathcalUC subseteq mathcalH where mathcalUC is the subset of thermal resources subject to unit commitment constraints\ns in mathcalS where s denotes a segment and mathcalS is the set of consumers segments for price-responsive demand curtailment\nmathcalO subseteq mathcalG where mathcalO is the subset of storage resources excluding heat storage and hydro storage\no in mathcalO where o denotes a storage technology in a set mathcalO\nmathcalO^sym subseteq mathcalO where mathcalO^sym corresponds to the set of energy storage technologies with equal (or symmetric) charge and discharge power capacities\nmathcalO^asym subseteq mathcalO where mathcalO^asym corresponds to the set of energy storage technologies with independently sized (or asymmetric) charge and discharge power capacities\nmathcalO^LDES subseteq mathcalO where mathcalO^LDES corresponds to the set of long-duration energy storage technologies for which inter-period energy exchange is permitted when using representative periods to model annual grid operations\nmathcalVS subseteq mathcalG where mathcalVS is the subset of co-located VRE and storage resources\nmathcalVS^pv subseteq mathcalVS where mathcalVS^pv corresponds to the set of co-located VRE and storage resources with a solar PV component\nmathcalVS^wind subseteq mathcalVS where mathcalVS^wind corresponds to the set of co-located VRE and storage resources with a wind component\nmathcalVS^inv subseteq mathcalVS where mathcalVS^inv corresponds to the set of co-located VRE and storage resources with an inverter component\nmathcalVS^stor subseteq mathcalVS where mathcalVS^stor corresponds to the set of co-located VRE and storage resources with a storage component\nmathcalVS^sym dc subseteq mathcalVS where mathcalVS^sym dc corresponds to the set of co-located VRE and storage resources with a storage DC component with equal (or symmetric) charge and discharge power capacities\nmathcalVS^sym ac subseteq mathcalVS where mathcalVS^sym ac corresponds to the set of co-located VRE and storage resources with a storage AC component with equal (or symmetric) charge and discharge power capacities\nmathcalVS^asym dc dis subseteq mathcalVS where mathcalVS^asym dc dis corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) discharge power capabilities\nmathcalVS^asym dc cha subseteq mathcalVS where mathcalVS^asym dc cha corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) charge power capabilities\nmathcalVS^asym ac dis subseteq mathcalVS where mathcalVS^asym ac dis corresponds to the set of co-located VRE and storage with a storage AC component with independently sized (or asymmetric) discharge power capabilities\nmathcalVS^asym ac cha subseteq mathcalVS where mathcalVS^asym ac cha corresponds to the set of co-located VRE and storage resources with a storage AC component with independently sized (or asymmetric) charge power capabilities\nmathcalVS^LDES subseteq mathcalVS where mathcalVS^LDES corresponds to the set of co-located VRE and storage resources with a long-duration energy storage component for which inter-period energy exchange is permitted when using representative periods to model annual grid operations\nmathcalW subseteq mathcalG where mathcalW set of hydroelectric generators with water storage reservoirs\nmathcalW^nocap subseteq mathcalW where mathcalW^nocap is a subset of set of $ \\mathcal{W}$ and represents resources with unknown reservoir capacity\nmathcalW^cap subseteq mathcalW where mathcalW^cap is a subset of set of $ \\mathcal{W}$ and represents resources with known reservoir capacity\nmathcalMR subseteq mathcalG where mathcalMR set of must-run resources\nmathcalDF subseteq mathcalG where mathcalDF set of flexible demand resources\nmathcalELECTROLYZER subseteq mathcalG where mathcalELECTROLYZER set of electrolyzer resources (optional set)\nmathcalG_p^ESR subseteq mathcalG where mathcalG_p^ESR is a subset of mathcalG that is eligible for Energy Share Requirement (ESR) policy constraint p\np in mathcalP where p denotes a instance in the policy set mathcalP\nmathcalP^ESR subseteq mathcalP Energy Share Requirement type policies\nmathcalP^CO_2 subseteq mathcalP CO_2 emission cap policies\nmathcalP^CO_2_mass subseteq mathcalP^CO_2 CO_2 emissions limit policy constraints, mass-based\nmathcalP^CO_2_demand subseteq mathcalP^CO_2 CO_2 emissions limit policy constraints, demand and emission-rate based\nmathcalP^CO_2_gen subseteq mathcalP^CO_2 CO_2 emissions limit policy constraints, generation emission-rate based\nmathcalP^CRM subseteq mathcalP Capacity reserve margin (CRM) type policy constraints\nmathcalP^MinTech subseteq mathcalP Minimum Capacity Carve-out type policy constraint\nmathcalZ^ESR_p subseteq mathcalZ set of zones eligible for ESR policy constraint p in mathcalP^ESR\nmathcalZ^CRM_p subseteq mathcalZ set of zones that form the locational deliverable area for capacity reserve margin policy constraint p in mathcalP^CRM\nmathcalZ^CO_2_pmass subseteq mathcalZ set of zones are under the emission cap mass-based cap-and-trade policy constraint p in mathcalP^CO_2_mass\nmathcalZ^CO_2_pdemand subseteq mathcalZ set of zones are under the emission cap demand-and-emission-rate based cap-and-trade policy constraint p in mathcalP^CO_2_demand\nmathcalZ^CO_2_pgen subseteq mathcalZ set of zones are under the emission cap generation emission-rate based cap-and-trade policy constraint p in mathcalP^CO2gen\nmathcalL_p^in subseteq mathcalL The subset of transmission lines entering Locational Deliverability Area of capacity reserve margin policy p in mathcalP^CRM\nmathcalL_p^out subseteq mathcalL The subset of transmission lines leaving Locational Deliverability Area of capacity reserve margin policy p in mathcalP^CRM\nmathcalQualified subseteq mathcalG where mathcalQualified is the subset of generation and storage resources eligible to supply electrolyzers within the same zone (optional set)","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/#Decision-Variables","page":"Notation","title":"Decision Variables","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"Notation Description\nOmega_yz in mathbbR_+ Installed capacity in terms of the number of units (each unit, being of size overlineOmega_yz^size) of resource y in zone z [Dimensionless] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the grid connection in [MW AC])\nOmega^energy_yz in mathbbR_+ Installed energy capacity of resource y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the storage component in MWh)\nOmega^charge_yz in mathbbR_+ Installed charging power capacity of resource y in zone z - only applicable for storage resources, y in mathcalO^asym [MW]\nOmega^pv_yz in mathbbR_+ Installed solar PV capacity of resource y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nOmega^wind_yz in mathbbR_+ Installed wind capacity of resource y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nOmega^inv_yz in mathbbR_+ Installed inverter capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nOmega^dcdis_yz in mathbbR_+ Installed storage DC discharge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nOmega^dccha_yz in mathbbR_+ Installed storage DC charge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nOmega^acdis_yz in mathbbR_+ Installed storage AC discharge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nOmega^accha_yz in mathbbR_+ Installed storage AC charge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nDelta_yz in mathbbR_+ Retired capacity of technology y from existing capacity in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the grid connection in MW AC)\nDelta^energy_yz in mathbbR_+ Retired energy capacity of technology y from existing capacity in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the storage component in MWh)\nDelta^charge_yz in mathbbR_+ Retired charging capacity of technology y from existing capacity in zone z - only applicable for storage resources, y in mathcalO^asym[MW]\nDelta^pv_yz in mathbbR_+ Retired solar PV capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nDelta^wind_yz in mathbbR_+ Retired wind capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nDelta^inv_yz in mathbbR_+ Retired inverter capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nDelta^dcdis_yz in mathbbR_+ Retired storage DC discharge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nDelta^dccha_yz in mathbbR_+ Retired storage DC charge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nDelta^acdis_yz in mathbbR_+ Retired storage AC discharge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nDelta^accha_yz in mathbbR_+ Retired storage AC charge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nDelta_yz^total in mathbbR_+ Total installed capacity of technology y in zone z [MW] (Note that co-located VRE and storage resources, this value represents the total capacity of the grid connection in MW AC)\nDelta_yz^totalenergy in mathbbR_+ Total installed energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that co-located VRE and storage resources, this value represents the total installed energy capacity of the storage component in MWh)\nDelta_yz^totalcharge in mathbbR_+ Total installed charging power capacity of technology y in zone z - only applicable for storage resources, y in mathcalO^asym [MW]\nDelta_yz^totalpv in mathbbR_+ Total installed solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nDelta_yz^totalwind in mathbbR_+ Total installed wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nDelta_yz^totalinv in mathbbR_+ Total installed inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nDelta_yz^totaldcdis in mathbbR_+ Total installed storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nDelta_yz^totaldccha in mathbbR_+ Total installed storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nDelta_yz^totalacdis in mathbbR_+ Total installed storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nDelta_yz^totalaccha in mathbbR_+ Total installed storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nbigtriangleupvarphi^max_l Additional transmission capacity added to line l [MW]\nTheta_yzt in mathbbR_+ Energy injected into the grid by technology y at time step t in zone z [MWh]\nTheta^pv_yzt in mathbbR_+ Energy generated by the solar PV component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MWh]\nTheta^wind_yzt in mathbbR_+ Energy generated by the wind component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MWh]\nTheta^dc_yzt in mathbbR_+ Energy discharged by the storage DC component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a discharge DC component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis [MWh]\nTheta^ac_yzt in mathbbR_+ Energy discharged by the storage AC component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a discharge AC component, y in mathcalVS^symac cup y in mathcalVS^asymacdis [MWh]\nPi_yzt in mathbbR_+ Energy withdrawn from grid by technology y at time step t in zone z [MWh]\nPi^dc_yzt in mathbbR_+ Energy withdrawn from the VRE and grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a charge DC component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha [MWh]\nPi^ac_yzt in mathbbR_+ Energy withdrawn from the VRE and grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a charge AC component, y in mathcalVS^symac cup y in mathcalVS^asymaccha [MWh]\nGamma_yzt in mathbbR_+ Stored energy level of technology y at end of time step t in zone z [MWh]\nLambda_szt in mathbbR_+ Non-served energy/curtailed demand from the price-responsive demand segment s in zone z at time step t [MWh]\nl_lt in mathbbR_+ Losses in line l at time step t [MWh]\nvarrho_yztin mathbbR_+ Spillage from a reservoir technology y at end of time step t in zone z [MWh]\nf_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves from technology y in zone z at time t\\footnote{Regulation reserve contribution are modeled to be symmetric, consistent with current practice in electricity markets}\nr_yzt in mathbbR_+ Upward spinning reserves contribution [MW] from technology y in zone z at time t (we are not modeling down spinning reserves since these are usually never binding for high variable renewable energy systems)\nf^charge_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves from charging storage technology y in zone z at time t\nf^discharge_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves from discharging storage technology y in zone z at time t\nr^charge_yzt in mathbbR_+ Upward spinning reserves contribution [MW] from charging storage technology y in zone z at time t\nr^discharge_yzt in mathbbR_+ Upward spinning reserves contribution [MW] from discharging storage technology y in zone z at time t\nr^unmet_t in mathbbR_+ Shortfall in provision of upward operating spinning reserves during each time period t in T\nf^pv_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the solar PV component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv\nr^pv_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the solar PV component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv\nf^wind_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the wind component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind\nr^wind_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the wind component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind\nf^dcdis_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage DC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis\nr^dcdis_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage DC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis\nf^dccha_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage DC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha\nr^dccha_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage DC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha\nf^acdis_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage AC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^symac cup y in mathcalVS^asymacdis\nr^acdis_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage AC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^symac cup y in mathcalVS^asymacdis\nf^accha_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage AC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^symac cup y in mathcalVS^asymaccha\nr^accha_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage AC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^symac cup y in mathcalVS^asymaccha\nalpha^ContingencyAux_yz in 01 Binary variable that is set to be 1 if the total installed capacity Delta^texttotal_yz 0 for any generator y in mathcalUC and zone z, and can be 0 otherwise\nPhi_lt in mathbbR_+ Power flow in line l at time step t [MWh]\ntheta_zt in mathbbR Volta phase angle in zone z at time step t [radian]\nv_yzt Commitment state of the generation cluster y in zone z at time t\nmathcalX_yzt Number of startup decisions, of the generation cluster y in zone z at time t\nzeta_yzt Number of shutdown decisions, of the generation cluster y in zone z at time t\nmathcalQ_on in mathbbR_+ Inventory of storage of type o at the beginning of input period n [MWh]\nDeltamathcalQ_om in mathbbR Excess storage inventory built up during representative period m [MWh]\nON^+_lt in 01 Binary variable to activate positive flows on line l in time t\nTransON^+_lt in mathbbR_+ Variable defining maximum positive flow in line l in time t [MW]\nTheta^CRM_yzt in mathbbR_+ \"Virtual\" energy discharged by a storage resource that contributes to the capacity reserve margin for technology y at time step t in zone z - only applicable for storage resources with activated capacity reserve margin policies, y in mathcalO [MWh]\nPi^CRM_yzt in mathbbR_+ \"Virtual\" energy withdrawn by a storage resource from the grid by technology y at time step t in zone z - only applicable for storage resources with activated capacity reserve margin policies, y in mathcalO [MWh]\nTheta^CRMdc_yzt in mathbbR_+ \"Virtual\" energy discharged by a storage DC component that contributes to the capacity reserve margin for technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nPi^CRMdc_yzt in mathbbR_+ \"Virtual\" energy withdrawn by a storage DC component from the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nTheta^CRMac_yzt in mathbbR_+ \"Virtual\" energy discharged by a storage AC component that contributes to the capacity reserve margin for technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nPi^CRMac_yzt in mathbbR_+ \"Virtual\" energy withdrawn by a storage AC component from the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nGamma^CRM_yzt in mathbbR_+ Total \"virtual\" state of charge being held in reserves for technology y at time step t in zone z - only applicable for standalone storage and co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalO cup y in mathcalVS^stor [MWh]","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/#Parameters","page":"Notation","title":"Parameters","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"Notation Description\nD_zt Electricity demand in zone z and at time step t [MWh]\ntau^period number of time steps in each representative period w in mathcalW^rep and each input period w in mathcalW^input\nomega_t weight of each model time step omega_t =1 forall t in T when modeling each time step of the year at an hourly resolution [1/year]\nn_s^slope Cost of non-served energy/demand curtailment for price-responsive demand segment s [$/MWh]\nn_s^size Size of price-responsive demand segment s as a fraction of the hourly zonal demand [%]\noverlineOmega_yz Maximum capacity of technology y in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the maximum grid connection capacity in MW AC)\nunderlineOmega_yz Minimum capacity of technology y in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the minimum grid connection capacity in MW AC)\noverlineOmega^energy_yz Maximum energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the maximum storage component in MWh)\nunderlineOmega^energy_yz Minimum energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the minimum storage component in MWh)\noverlineOmega^charge_yz Maximum charging power capacity of technology y in zone z - only applicable for storage resources, y in mathcalO^asym [MW]\nunderlineOmega^charge_yz Minimum charging capacity of technology y in zone z- only applicable for storage resources, y in mathcalO^asym [MW]\noverlineOmega^pv_yz Maximum solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nunderlineOmega^pv_yz Minimum solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\noverlineOmega^wind_yz Maximum wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nunderlineOmega^wind_yz Minimum wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\noverlineOmega^inv_yz Maximum inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nunderlineOmega^inv_yz Minimum inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\noverlineOmega^dcdis_yz Maximum storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nunderlineOmega^dcdis_yz Minimum storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\noverlineOmega^dccha_yz Maximum storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nunderlineOmega^dccha_yz Minimum storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\noverlineOmega^acdis_yz Maximum storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nunderlineOmega^acdis_yz Minimum storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\noverlineOmega^accha_yz Maximum storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nunderlineOmega^accha_yz Minimum storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\noverlineDelta_yz Existing installed capacity of technology y in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the existing installed capacity of the grid connection in [MW AC])\noverlineDelta^energy_yz Existing installed energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the existing installed energy capacity of the storage component in MWh)\noverlineDelta^charge_yz Existing installed charging capacity of technology y in zone z - only applicable for storage resources, y in mathcalO [MW]\noverlineDelta^pv_yz Existing installed solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\noverlineDelta^wind_yz Existing installed wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\noverlineDelta^inv_yz Existing installed inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\noverlineDelta^dcdis_yz Existing installed storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\noverlineDelta^dccha_yz Existing installed storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\noverlineDelta^acdis_yz Existing installed storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\noverlineDelta^dccha_yz Existing installed storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymdccha [MW AC]\noverlineOmega_yz^size Unit size of technology y in zone z [MW]\npi_yz^INVEST Investment cost (annual amortization of total construction cost) for power capacity of technology y in zone z [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the grid connection capacity in $/MW AC-yr)\npi_yz^INVESTenergy Investment cost (annual amortization of total construction cost) for energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^pv [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the energy capacity of the storage component in $/MWh-yr)\npi_yz^INVESTcharge Investment cost (annual amortization of total construction cost) for charging power capacity of technology y in zone z - only applicable for storage resources, y in mathcalO [$/MW-yr]\npi_yz^INVESTpv Investment cost (annual amortization of total construction cost) for solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [$/MW DC-yr]\npi_yz^INVESTwind Investment cost (annual amortization of total construction cost) for wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [$/MW AC-yr]\npi_yz^INVESTinv Investment cost (annual amortization of total construction cost) for inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [$/MW AC-yr]\npi_yz^INVESTdcdis Investment cost (annual amortization of total construction cost) for storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^asymdcdis [$/MW DC-yr]\npi_yz^INVESTdccha Investment cost (annual amortization of total construction cost) for storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^asymdccha [$/MW DC-yr]\npi_yz^INVESTacdis Investment cost (annual amortization of total construction cost) for storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^asymacdis [$/MW AC-yr]\npi_yz^INVESTaccha Investment cost (annual amortization of total construction cost) for storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^asymaccha [$/MW AC-yr]\npi_yz^FOM Fixed O&M cost of technology y in zone z [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the grid connection capacity in $/MW AC-yr)\npi_yz^FOMenergy Fixed O&M cost of energy component of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the storage energy capacity in $/MWh-yr)\npi_yz^FOMcharge Fixed O&M cost of charging power component of technology y in zone z - only applicable for storage resources, y in mathcalO [$/MW-yr]\npi_yz^FOMpv Fixed O&M cost of the solar PV component of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [$/MW DC-yr]\npi_yz^FOMwind Fixed O&M cost of the wind component of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [$/MW AC-yr]\npi_yz^FOMinv Fixed O&M cost of the inverter component of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [$/MW AC-yr]\npi_yz^FOMdcdis Fixed O&M cost of the storage DC discharge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [$/MW DC-yr]\npi_yz^FOMdccha Fixed O&M cost of the storage DC charge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [$/MW DC-yr]\npi_yz^FOMacdis Fixed O&M cost of the storage AC discharge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [$/MW AC-yr]\npi_yz^FOMaccha Fixed O&M cost of the storage AC charge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [$/MW AC-yr]\npi_yz^VOM Variable O&M cost of technology y in zone z [$/MWh]\npi_yz^VOMcharge Variable O&M cost of charging technology y in zone z - only applicable for storage and demand flexibility resources, y in mathcalO cup mathcalDF [$/MWh]\npi_yz^VOMpv Variable O&M cost of the solar PV component of technology y in zone z - only applicable to co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [$/MWh]\npi_yz^VOMwind Variable O&M cost of the wind component of technology y in zone z - only applicable to co-located VRE and storage resources with a wind component, y in mathcalVS^wind [$/MWh]\npi_yz^VOMdcdis Variable O&M cost of the storage DC discharge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis [$/MWh]\npi_yz^VOMdccha Variable O&M cost of the storage DC charge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha [$/MWh]\npi_yz^VOMacdis Variable O&M cost of the storage AC discharge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^symac cup y in mathcalVS^asymacdis [$/MWh]\npi_yz^VOMaccha Variable O&M cost of the storage AC charge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^symac cup y in mathcalVS^asymaccha [$/MWh]\npi_yz^FUEL Fuel cost of technology y in zone z [$/MWh]\npi_yz^START Startup cost of technology y in zone z [$/startup]\nupsilon^reg_yz Maximum fraction of capacity that a resource y in zone z can contribute to frequency regulation reserve requirements\nupsilon^rsv_yz Maximum fraction of capacity that a resource y in zone z can contribute to upward operating (spinning) reserve requirements\npi^Unmet_rsv Cost of unmet spinning reserves in [$/MW]\nepsilon^demand_reg Frequency regulation reserve requirement as a fraction of forecasted demand in each time step\nepsilon^vre_reg Frequency regulation reserve requirement as a fraction of variable renewable energy generation in each time step\nepsilon^demand_rsv Operating (spinning) reserve requirement as a fraction of forecasted demand in each time step\nepsilon^vre_rsv Operating (spinning) reserve requirement as a fraction of forecasted variable renewable energy generation in each time step\nepsilon_yz^CO_2 CO_2 emissions per unit energy produced by technology y in zone z [metric tons/MWh]\nepsilon_yzp^MinTech Equals to 1 if a generator of technology y in zone z is eligible for minimum capacity carveout policy p in mathcalP^MinTech, otherwise 0\nREQ_p^MinTech The minimum capacity requirement of minimum capacity carveout policy p in mathcalP^MinTech [MW]\nREQ_p^MaxTech The maximum capacity requirement of minimum capacity carveout policy p in mathcalP^MinTech [MW]\nepsilon_yzp^CRM Capacity derating factor of technology y in zone z for capacity reserve margin policy p in mathcalP^CRM [fraction]\nRM_zp^CRM Reserve margin of zone z of capacity reserve margin policy p in mathcalP^CRM [fraction]\nepsilon_zpmass^CO_2 Emission budget of zone z under the emission cap p in mathcalP^CO_2_mass [ million of metric tonnes]\nepsilon_zpdemand^CO_2 Maximum carbon intensity of the demand of zone z under the emission cap p in mathcalP^CO_2_demand [metric tonnes/MWh]\nepsilon_zpgen^CO_2 Maximum emission rate of the generation of zone z under the emission cap p in mathcalP^CO_2_gen [metric tonnes/MWh]\nrho_yz^min Minimum stable power output per unit of installed capacity for technology y in zone z [%]\nrho_yzt^max Maximum available generation per unit of installed capacity during time step t for technology y in zone z [%]\nrho_yzt^maxpv Maximum available generation per unit of installed capacity for the solar PV component of a co-located VRE and storage resource during time step t for technology y in zone z [%]\nrho_yzt^maxwind Maximum available generation per unit of installed capacity for the wind component of a co-located VRE and storage resource during time step t for technology y in zone z [%]\nVREIndex_yz Resource bin index for VRE technology y in zone z. VREIndex_yz=1 for the first bin, and VREIndex_yz=0 for remaining bins. Only defined for yin mathcalVRE\nvarphi^map_lz Topology of the network, for line l: varphi^map_lz=1 for start zone z, - 1 for end zone z, 0 otherwise.\nmathcalB_l DC-OPF coefficient for line l [MWh]\nDelta theta^max_l Maximum voltage phase angle difference for line l [radian]\neta_yz^loss Self discharge rate per time step per unit of installed capacity for storage technology y in zone z [%]\neta_yz^charge Single-trip efficiency of storage charging/demand deferral for technology y in zone z [%]\neta_yz^discharge Single-trip efficiency of storage (and hydro reservoir) discharging/demand satisfaction for technology y in zone z [%]\neta_yz^chargedc Single-trip efficiency of storage DC charging/demand deferral for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^dischargedc Single-trip efficiency of storage DC discharging/demand satisfaction for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^chargeac Single-trip efficiency of storage AC charging/demand deferral for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^dischargeac Single-trip efficiency of storage AC discharging/demand satisfaction for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^inverter Inverter efficiency representing losses from converting DC to AC power and vice versa for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^ILRpv Inverter loading ratio (the solar PV capacity sizing to the inverter capacity built) of technology y in zone z for co-located VRE and storage resources with a solar PV component [%]\neta_yz^ILRwind Inverter loading ratio (the wind PV capacity sizing to the grid connection capacity built) of technology y in zone z for co-located VRE and storage resources with a wind component [%]\nmu_yz^stor Ratio of energy capacity to discharge power capacity for storage technology (and hydro reservoir) y in zone z [MWh/MW]\nmu_yz^dcstor Ratio of discharge power capacity to energy capacity for the storage DC component of co-located VRE and storage technology y in zone z [MW/MWh]\nmu_yz^acstor Ratio of discharge power capacity to energy capacity for the storage AC component of co-located VRE and storage technology y in zone z [MW/MWh]\nmu_yz^mathcalDF Maximum percentage of hourly demand that can be shifted by technology y in zone z [%]\nkappa_yz^up Maximum ramp-up rate per time step as percentage of installed capacity of technology y in zone z [%/hr]\nkappa_yz^down Maximum ramp-down rate per time step as percentage of installed capacity of technology y in zone z [%/hr]\ntau_yz^up Minimum uptime for thermal generator type y in zone z before new shutdown [hours].\ntau_yz^down Minimum downtime or thermal generator type y in zone z before new restart [hours].\ntau_yz^advance maximum time by which flexible demand resource can be advanced [hours]\ntau_yz^delay maximum time by which flexible demand resource can be delayed [hours]\neta_yz^dflex energy losses associated with shifting the flexible demand [%]\nmu_pz^mathcalESR share of total demand in each model zone z in mathcalESR^p that must be served by qualifying renewable energy resources y in mathcalG^ESR_p\nf(n) Mapping each modeled period n in mathcalN to corresponding representative period w in mathcalW\neta_y^electrolyzer Efficiency of the electrolyzer y in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced [MWh/t] (optional parameter)\n$ ^hydrogen_y Price of hydrogen per metric tonne for electrolyzer y [$/t] (optional parameter)\nmathcalMin kt_y Minimum annual quantity of hydrogen that must be produced by electrolyzer y in kilotonnes [kt] (optional parameter)","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Getting_Started/commercial_solvers/#Using-commercial-solvers:-Gurobi-or-CPLEX","page":"Commertial solvers","title":"Using commercial solvers: Gurobi or CPLEX","text":"","category":"section"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"If you want to use the commercial solvers Gurobi or CPLEX:","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"Make sure you have a valid license and the actual solvers for either of Gurobi or CPLEX installed on your machine\nAdd Gurobi or CPLEX to the Julia Project.","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"$ julia --project=/home/youruser/GenX\n\njulia> \n(GenX) pkg> add Gurobi\n-or-\n(GenX) pkg> add CPLEX","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"#TODO: Add instructions for adding Gurobi or CPLEX to the Julia Project with the new PR. ","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"Edit the Run.jl file to use the commercial solver. For example, to use Gurobi, you can add the following lines to the Run.jl file:","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"using Gurobi\nusing GenX\n\nrun_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"warning: Warning\nNote that if you have not already installed the required Julia packages or you do not have a valid Gurobi license on your host machine, you will receive an error message and Run.jl will not run to completion.","category":"page"},{"location":"additional_third_party_extensions/#Additional-Third-Party-Extensions-to-GenX","page":"Third Party Extensions","title":"Additional Third Party Extensions to GenX","text":"","category":"section"},{"location":"additional_third_party_extensions/#pygenx:-Python-interface-for-GenX","page":"Third Party Extensions","title":"pygenx: Python interface for GenX","text":"","category":"section"},{"location":"additional_third_party_extensions/","page":"Third Party Extensions","title":"Third Party Extensions","text":"Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation.","category":"page"},{"location":"additional_third_party_extensions/#Simple-GenX-Case-Runner:-For-automated-sequential-batch-run-for-GenX","page":"Third Party Extensions","title":"Simple GenX Case Runner: For automated sequential batch run for GenX","text":"","category":"section"},{"location":"additional_third_party_extensions/","page":"Third Party Extensions","title":"Third Party Extensions","text":"It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner","category":"page"},{"location":"Model_Reference/Resources/must_run/#Must-Run","page":"Must Run","title":"Must Run","text":"","category":"section"},{"location":"Model_Reference/Resources/must_run/","page":"Must Run","title":"Must Run","text":"Modules = [GenX]\nPages = [\"must_run.jl\"]","category":"page"},{"location":"Model_Reference/Resources/must_run/#GenX.must_run!-Tuple{JuMP.Model, Dict, Dict}","page":"Must Run","title":"GenX.must_run!","text":"must_run!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the constraints for operation of `must-run' or non-dispatchable resources, such as rooftop solar systems that do not receive dispatch signals, run-of-river hydroelectric facilities without the ability to spill water, or cogeneration systems that must produce a fixed quantity of heat in each time step. This resource type can also be used to model baseloaded or self-committed thermal generators that do not respond to economic dispatch.\n\nFor must-run resources (yin mathcalMR) output in each time period t must exactly equal the available capacity factor times the installed capacity, not allowing for curtailment. These resources are also not eligible for contributing to frequency regulation or operating reserve requirements.\n\nbeginaligned\nTheta_yzt = rho^max_yzttimes Delta^total_yz\nhspace4 cm forall y in mathcalMR z in mathcalZt in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Tutorial-3:-K-Means-and-Time-Domain-Reduction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"A good tool to reduce computation time of GenX is to use Time-domain reduction. Time Domain Reduction is a method that selects a smaller set of time steps from the data in a way that reduces computation time while still capturing the main information of the model. In this tutorial, we go over how TDR works in GenX and how it uses K-means clustering to choose the optimal time steps. For more information on TDR in capacity expansion models, see Mallapragada et al.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Table-of-Contents","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Time Domain Reduction\nK-Means Clustering\nResults of Time Domain Reduction\nReconstruction\nExtreme Periods\nObjective Values and Representative Periods","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Time-Domain-Reduction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Time Domain Reduction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To see how Time Domain Reduction works, let's look at the Doad_data in example_systems/1_three_zones:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# First, load all packages needed\nusing DataFrames\nusing CSV\nusing VegaLite\nusing YAML\nusing PlotlyJS\nusing Plots\nusing Clustering\nusing ScikitLearn\n@sk_import datasets: (make_blobs)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"WARNING: redefinition of constant make_blobs. This may fail, cause incorrect answers, or produce other errors.\nPyObject ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"case = joinpath(\"example_systems/1_three_zones\");","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads = CSV.read(joinpath(case,\"system/Demand_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"
8760×12 DataFrame
8735 rows omitted
RowVollDemand_SegmentCost_of_Demand_Curtailment_per_MWMax_Demand_Curtailment$/MWhRep_PeriodsTimesteps_per_Rep_PeriodSub_WeightsTime_IndexDemand_MW_z1Demand_MW_z2Demand_MW_z3
String7String3String7String7String7String3String7String7Int64Int64Int64Int64
15000011120001876087601785022421070
220.90.0418002742421201012
330.550.0241100371072029969
440.20.003400469471984947
5569221977944
6670452012960
7773072087996
88754421541029
99794622691083
1010834023821137
1111857824491169
1212866624741181
1313870724871187
874987491073030641463
875087501055030131439
875187511043829811423
875287521046929901427
875387531122832061531
875487541190834011624
875587551156233021576
87568756992337971339
87578757946136211277
87588758901834521217
87598759855132811154
87608760808931061092
","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The columns to note in this file are Rep_Periods, TimeSteps_Per_Rep_Period, Time_Index, and Demand_MW_. This file shows the number of time steps used in GenX before applying TDR, i.e. every hour in a year, totaling 8,760 hours. This means that there is only one representative period, as seen in Rep_Periods.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"TDR performs a \"reduction\" into a specified number of \"representative periods\", paring down the input data into a smaller set. The representative periods are then used in the GenX algorithm in place of the entire input data to reduce computation time. The TDR algorithm selects the representative periods to be the set of data whose results in GenX best match the results of the entire input data. To do this, TDR using k-means clustering, described in the next section.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"When TDR is used, the file time_domain_reduction_settings.yml is called with a variety of specified settings, shown below:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings = YAML.load(open(joinpath(case,\"settings/time_domain_reduction_settings.yml\")))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 15 entries:\n \"IterativelyAddPeriods\" => 1\n \"ExtremePeriods\" => Dict{Any, Any}(\"Wind\"=>Dict{Any, Any}(\"System\"=>Di…\n \"UseExtremePeriods\" => 1\n \"MinPeriods\" => 8\n \"MaxPeriods\" => 11\n \"DemandWeight\" => 1\n \"ClusterFuelPrices\" => 1\n \"nReps\" => 100\n \"MultiStageConcatenate\" => 0\n \"Threshold\" => 0.05\n \"TimestepsPerRepPeriod\" => 168\n \"IterateMethod\" => \"cluster\"\n \"ScalingMethod\" => \"S\"\n \"ClusterMethod\" => \"kmeans\"\n \"WeightTotal\" => 8760","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"For descriptions of all settings, see cluster_inputs in the documentation.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads |>\n@vlplot(:line, \n x=:Time_Index, y=:Demand_MW_z1, title=\"MW Load per hour, No TDR\",\n width=600,height=400,linewidth=.01)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"(Image: svg)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"As in Tutorial 1: Configuring Settings, 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.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ = YAML.load(open((joinpath(case,\"settings/genx_settings.yml\"))))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 19 entries:\n \"NetworkExpansion\" => 1\n \"ModelingToGenerateAlternativeIterations\" => 3\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 0\n \"PrintModel\" => 0\n \"TimeDomainReduction\" => 1\n \"Trans_Loss_Segments\" => 1\n \"CapacityReserveMargin\" => 0\n \"ModelingtoGenerateAlternativeSlack\" => 0.1\n \"MethodofMorris\" => 0\n \"StorageLosses\" => 1\n \"MultiStage\" => 0\n \"OverwriteResults\" => 0\n \"UCommit\" => 2\n \"ModelingToGenerateAlternatives\" => 0\n \"MaxCapReq\" => 0\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To run GenX without TDR, we start by editing the settings to set TimeDomainReduction to 0:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ[\"TimeDomainReduction\"] = 0\ngenx_settings_TZ ## Output settings","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 13 entries:\n \"NetworkExpansion\" => 1\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 0\n \"TimeDomainReduction\" => 0\n \"Trans_Loss_Segments\" => 1\n \"CapacityReserveMargin\" => 0\n \"StorageLosses\" => 1\n \"ComputeConflicts\" => 1\n \"UCommit\" => 2\n \"MaxCapReq\" => 0\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Then we write the edited settings to the file path:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"YAML.write_file((joinpath(case,\"settings/genx_settings.yml\")), genx_settings_TZ)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"And run it using include. (Note: this process will take a few minutes):","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"@time include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"This took a little while to run, and would take even longer for larger systems. Let's see how we can get the run time down using Time Domain Reduction. The next sections go over how K-means clustering is used to perform TDR, and how to interpret the resulting files in GenX.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#K-means-clustering","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"K-means clustering","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Let's go over how TDR works. To perform TDR, GenX uses K-means clustering. K-means is an optimization method that clusters data into several groups based on their proximity to \"centers\" determined by the algorithm. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"K-means finds a set number of groups such that the variance between the distance of each point in the group to the mean of the group is minimized. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"beginalign*\nmathoparg minlimits_mathbfS sum_i = 1^k sum_x in S_i x - mu_i^2 \nendalign*","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Where mathbfS = S_1 S_k are the clusters, with x denoting the elements of the clusters, and mu_i the mean of each cluster, i.e. the mean of the distances from each point to the center of the cluster. By taking the argmin over mathbfS, the points x are clustered into groups where their distance to the center is the smallest. For more information on how k-means works, see the Wikipedia. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"GenX uses the package Clustering.jl, with documentation here. As an example, using the package ScikitLearn.jl, let's generate data that can cluster easily.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"centers = 5\nX, y = make_blobs(n_samples=50,centers=centers); # From scikit-learn\nb = DataFrame(X,:auto)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Note that clustering works for data without obvious groupings, but using blobs as an example makes k-means easier to visualize.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"plotly()\nPlots.scatter(b[!,\"x1\"],b[!,\"x2\"],legend=false,title=\"Before K-means Clustering\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Now we use the function kmeans, which is also used in src/time_domain_reduction in GenX.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"R = kmeans(transpose(Matrix(b)),centers)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"kmeans returns three outputs: assignments, centers, and counts. Assignments shows to which cluster each points belongs, centers shows where the center coordinates of each cluster are, and counts shows how many points belong to each cluster.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"println(\"Assignments = \",R.assignments)\nprintln(\"\")\nprintln(\"Counts = \",R.counts)\nprintln(\"\")\nprintln(\"Centers:\")\nR.centers","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"plotly()\nPlots.scatter(b[!,\"x1\"],b[!,\"x2\"],legend=false,marker_z=R.assignments,c=:lightrainbow,title=\"After K-means Clustering\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"In GenX, the representative periods are the centers of the clusters, each representing one week of the year. In the above example that would mean there are 52 data points gathered into 11 clusters (to see this for yourself, change make_blobs to have 52 data points and 11 clusters.)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Results-of-Time-Domain-Reduction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Results of Time Domain Reduction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To visualize the results of TDR, we'll set TDR = 1 back in the genx_settings.yml file in Example_Systems_Tutorials/SmallNewEngland/OneZone/:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ[\"TimeDomainReduction\"] = 1;","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"YAML.write_file((joinpath(case,\"settings/genx_settings.yml\")), genx_settings_TZ)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"And run GenX again with TDR:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"@time include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Csv files with the results of TDR are generated automatically in a folder called TDR_results found within the same folder containing the input csv files, in this case Example_Systems_Tutorials/SmallNewEngland/OneZone. The csv files in this folder show the files used in Run.jl that have been pared down from the initial input files.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"As an example, consider the input file Fuels_data.csv:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Fuels_original = CSV.read(joinpath(case,\"system/Fuels_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Compared to TDR_Results/Fuels_data.csv:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Fuels_TDR = CSV.read(joinpath(case,\"TDR_Results/Fuels_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"As you can see, the original has all 8,760 hours, while the TDR version only has 1,848 hours.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_TDR = CSV.read(joinpath(case,\"TDR_Results/Demand_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The 1,848 hours are divided into 11 sections of 168 hours, with each section representing one week of the original data. The number of hours per representative period is set in time_domain_reduction_settings.yml. Also specified in the file are the minimum and maximum number of clusters we would like to have (in this case 8 and 11). The k-means algorithm will then select the number of clusters that should be sufficient to capture the GenX model in fewer time steps (in this case 11).","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Gen_TDR = CSV.read(joinpath(case,\"TDR_Results/Generators_variability.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"generators = CSV.read(joinpath(case,\"system/Generators_variability.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Below, we create arrays out of the representative weeks and plot them on the same plot used in the beginning of this tutorial. The file Period_map shows which periods (weeks) are used in TDR and which time step corresponds to each period:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Period_map = CSV.read(joinpath(case,\"TDR_Results/Period_map.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Find array of unique representative periods\nrep_periods = unique(Period_map[!,\"Rep_Period\"])\n\n# Create an array of the time steps and MW values of each representative period\nweeks_load = []\nfor i in rep_periods\n week_temp_loads = [repeat([i],168) loads[(168*i-167):168*i,\"Time_Index\"] loads[(168*i-167):168*i,\"Demand_MW_z1\"]]\n weeks_load = [weeks_load; week_temp_loads]\nend\n\n# Combine with Total (pre TDR)\nloads_plot = [repeat([\"Total\"],8760) loads[!,\"Time_Index\"] loads[!,\"Demand_MW_z1\"]];\n\n# Add column names and convert column type\nloads_with_TDR = [loads_plot; weeks_load]\nloads_with_TDR = DataFrame(loads_with_TDR ,[\"Week\",\"hour\", \"MW\"])\nloads_with_TDR[!,:hour] = convert.(Int64,loads_with_TDR[!,:hour]);\nloads_with_TDR[!,:MW] = convert.(Float64,loads_with_TDR[!,:MW]);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_with_TDR |>\n@vlplot(mark={:line},\n x={:hour,title=\"Time Step (hours)\",labels=\"Week:n\"}, y={:MW,title=\"Load (MW)\"},\n color={\"Week:n\", scale={scheme=\"paired\"},sort=\"decsending\"}, title=\"MW Load per hour with TDR Representative Weeks\",\n width=845,height=400)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"(Image: svg)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"TDR is performed for four total data sets: demand (found in Demand.csv), wind and solar (found in Generators_variability.csv), and fuel prices (found in Fuels.csv). Above is just the demand load for one of the three total nodes in the example system, which is why the data may not appear to \"represent\" all 52 weeks (notice there are fewer representative periods in the fall). Instead, the periods more accurately represent all the data time series combined, including some other parts of the data not seen in this particular plot.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Extreme-Periods-Off","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Extreme Periods Off","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"GenX has a feature called ExtremePeriods, which forces kmeans to include the highest and lowest points in the algorithm. This is done to ensure outliers are used, which is needed in planning energy capacity as the system needs to be able to account for outliers in energy needs. In the above graph, we can see that energy needs peak during the summer, and that the week with the highest load demand is included as a representative week. Let's try turning extreme periods off, and see what happens. move this up","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings[\"ExtremePeriods\"] = 0;\nYAML.write_file(joinpath(case,\"settings/genx_settings.yml\"), genx_settings_TZ);\nrm(joinpath(case,\"TDR_results\"), recursive=true) ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Loads_TDR2 = CSV.read(joinpath(case,\"TDR_Results/Load_data.csv\"),DataFrame,missingstring=\"NA\");\nPeriod_map2 = CSV.read(joinpath(case,\"TDR_Results/Period_map.csv\"),DataFrame,missingstring=\"NA\");","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"rep_periods2 = unique(Period_map2[!,\"Rep_Period\"])\n\nweeks2 = []\nfor i in rep_periods2\n week_temp = [repeat([i],168) loads[(168*i-167):168*i,\"Time_Index\"] loads[(168*i-167):168*i,\"Demand_MW_z1\"]]\n weeks2 = [weeks2; week_temp]\nend\n\nweeks2 = [weeks2 repeat([\"Off\"],1848)];","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_plotOff = [repeat([\"Total\"],8760) loads[!,\"Time_Index\"] loads[!,\"Demand_MW_z1\"] repeat([\"Off\"],8760) ];\nloads_with_TDR[!,\"Extreme_Periods\"] = repeat([\"On\"],length(loads_with_TDR[!,1]));\nloads_with_TDR2 = [loads_plotOff; weeks2]","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_with_TDR2 = DataFrame(loads_with_TDR2 ,[\"Week\",\"hour\",\"MW\",\"Extreme_Periods\"])\nloads_with_TDR2[!,:hour] = convert.(Int64,loads_with_TDR2[!,:hour]);\nloads_with_TDR2[!,:MW] = convert.(Float64,loads_with_TDR2[!,:MW]);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Define a new color scheme to accomodate more periods\nmyscheme = [\"#a6cee3\",\"#a6cee3\",\"#1f78b4\",\"#b2df8a\",\"#33a02c\",\"#fb9a99\",\"#e31a1c\",\"#fdbf6f\",\"#ff7f00\",\n \"#cab2d6\",\"#6a3d9a\",\"#ffff99\",\"#b15928\",\"#b1ff00\",\"#095768\",\"#ce7e00\",\"#b4a7d6\"];\n[loads_with_TDR; loads_with_TDR2] |>\n@vlplot(mark={:line}, row=\"Extreme_Periods:n\",\n x={:hour,title=\"Time Step (hours)\",labels=\"Week:n\"}, y={:MW,title=\"Load (MW)\"},\n color={\"Week:n\", scale={scheme=\"paired\"},sort=\"decsending\"}, \n title=\"MW Load per hour with TDR Representative Weeks, Extreme Periods Off\",\n width=845,height=300)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"(Image: svg)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The first plot (with Extreme Periods off) may not have the week with the highest peak highlighted. If the week with the highest demand is highlighted, try re-running the cell with Extreme Periods Off plotting the results.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Turn Extreme Periods back on:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings[\"ExtremePeriods\"] = 1;\nYAML.write_file(joinpath(case,\"settings/time_domain_reduction_settings.yml\"), time_domain_reduction_settings);\nrm(joinpath(case,\"TDR_results\"), recursive=true) ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Reconstruction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Reconstruction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Below is a plot of a reconstruction of the data using only the weeks isolated as representative periods. This is what GenX reads when it runs the solver with TDR on.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"recon = []\nrecon_noex = []\nfor i in range(1,52)\n index = Period_map[i,\"Rep_Period\"]\n recon_temp = [repeat([index],168) collect((168*i-167):168*i) loads[(168*index-167):168*index,\"Demand_MW_z1\"]]\n recon = [recon; recon_temp]\n \n index2 = Period_map2[i,\"Rep_Period\"]\n recon_noex_temp = [repeat([index2],168) collect((168*i-167):168*i) loads[(168*index2-167):168*index2,\"Demand_MW_z1\"]]\n recon_noex = [recon_noex; recon_noex_temp]\nend\n\nrecon = DataFrame(recon,[\"Week\",\"hour\", \"MW\"])\nrecon[!,:hour] = convert.(Int64,recon[!,:hour]);\nrecon[!,:MW] = convert.(Float64,recon[!,:MW]);\nrecon[!,\"Extreme_Periods\"] = repeat([\"On\"],length(recon[!,1]));\n\nrecon_noex = [recon_noex repeat([\"Off\"],8736)];\nrecon_noex = DataFrame(recon_noex,[\"Week\",\"hour\", \"MW\", \"Extreme_Periods\"])\nrecon_noex[!,:hour] = convert.(Int64,recon_noex[!,:hour]);\nrecon_noex[!,:MW] = convert.(Float64,recon_noex[!,:MW]);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"plotlyjs()\nG1 = Plots.plot(recon_noex[!,:hour], recon_noex[!,:MW], linewidth=1.7,\n xticks=0:500:9000,xlabelfontsize=8,\n yticks=0:2000:18000,yformatter =:plain,ylims=(0,18000), ylabel=\"Demand (MW)\",\n legend=false, title=\"Reconstruction, Extreme Periods Off\", hover=recon_noex[!,:Week],\n color=recon_noex[!,:Week],size=(845,800),palette=:Paired_12)\n\nG2 = Plots.plot(recon[!,:hour], recon[!,:MW], linewidth=1.7,\n xticks=0:500:9000,xlabel=\"Time Step (Hours)\",xlabelfontsize=8,\n ylims=(0,18000),yticks=0:2000:18000,yformatter =:plain,ylabel=\"Demand (MW)\",\n legend=false, title=\"Reconstruction, Extreme Periods On\",hover=recon[!,:Week],\n color=recon[!,:Week],size=(845,800),palette=:Paired_12)\n\nPlots.plot(G1,G2,layout=(2,1))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Each color represents one of the representative weeks.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The range of 8-11 representative periods was chosen by the developers because it was deemed to be the smallest set that still matches the optimal value of the data well. The next section of this Tutorial goes over how the optimal values of the data change as the number of representative periods changes.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Objective-Values-and-Representative-Periods","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Objective Values and Representative Periods","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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 GenX Outputs.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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 Objective Function in the documentation. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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 example_systems/1_three_zone with a variety of minimum and maximum total periods.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 15 entries:\n \"IterativelyAddPeriods\" => 1\n \"ExtremePeriods\" => 1\n \"UseExtremePeriods\" => 1\n \"MinPeriods\" => 8\n \"MaxPeriods\" => 11\n \"DemandWeight\" => 1\n \"ClusterFuelPrices\" => 1\n \"nReps\" => 100\n \"MultiStageConcatenate\" => 0\n \"Threshold\" => 0.05\n \"TimestepsPerRepPeriod\" => 168\n \"IterateMethod\" => \"cluster\"\n \"ScalingMethod\" => \"S\"\n \"ClusterMethod\" => \"kmeans\"\n \"WeightTotal\" => 8760","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Each time Run.jl is run, a new results folder appears in the model folder. These folders are not overwritten. So far, we've run the model three times, so we should have three results folders in the 1threezones folder, but you may have more if you've run the model more. To ensure that the following code works, we'll delete any results folders beyond the original.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"folders = cd(readdir,case)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" 10-element Vector{String}:\n \".DS_Store\"\n \"README.md\"\n \"Run.jl\"\n \"policies\"\n \"resources\"\n \"results\"\n \"results_1\"\n \"results_2\"\n \"settings\"\n \"system\"","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"for folder in folders\n if length(folder) >= 8 && folder[1:8] == \"results_\"\n rm(\"example_systems/1_three_zones/\" * folder,recursive=true) \n end\nend\n \ncd(readdir,case) ## Make sure they were deleted","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" 8-element Vector{String}:\n \".DS_Store\"\n \"README.md\"\n \"Run.jl\"\n \"policies\"\n \"resources\"\n \"results\"\n \"settings\"\n \"system\"","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To demonstrate how the objective value changes as the number of representative periods does, we'll run GenX ten times, each with a different number of periods, and plot the objective values.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Change MinPeriods and Max Periods, run `Run.jl`\n# For simplicity, keep min and max periods the same\nrep_periods = [4, 8, 12, 24, 36, 48]\ntimes = [0.0,0.0,0.0,0.0,0.0,0.0]\n\nfor i in range(1,6)\n println(\" \")\n println(\"----------------------------------------------------\")\n println(\"Iteration \",i)\n println(\"Periods = \",rep_periods[i])\n println(\"----------------------------------------------------\")\n time_domain_reduction_settings[\"MinPeriods\"] = rep_periods[i]\n time_domain_reduction_settings[\"MaxPeriods\"] = rep_periods[i]\n if \"TDR_Results\" in cd(readdir,case)\n rm(joinpath(case,\"TDR_results\", recursive=true)) \n end\n println(\" \")\n YAML.write_file(joinpath(case,\"settings/time_domain_reduction_settings.yml\"), time_domain_reduction_settings)\n time = @elapsed include(\"example_systmes/1_three_zones/Run.jl\")\n times[i] = time\nend","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Note that as the number of periods increases, so does the time it takes to run.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Now, let's check that we have the correct Results folders and process the objecive values to plot. There should be seven results folders, including the original results.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"cd(readdir,case)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The objective value is found in the files costs.csv and status.csv.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"status = CSV.read(joinpath(case,\"results/status.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" 1×3 DataFrame\n Row Status Solve Objval\n String Float64 String\n ─────────────────────────────────────\n 1\t OPTIMAL\t53.9481\t 9762.44","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Find objective values from each results folder:\n\nOV_noTDR = CSV.read(joinpath(case,\"Results/status.csv\"),DataFrame);\nOV_RP4 = CSV.read(joinpath(case,\"Results_1/status.csv\"),DataFrame);\nOV_RP8 = CSV.read(joinpath(case,\"Results_2/status.csv\"),DataFrame);\nOV_RP12 = CSV.read(joinpath(case,\"Results_3/status.csv\"),DataFrame);\nOV_RP24 = CSV.read(joinpath(case,\"Results_4/status.csv\"),DataFrame);\nOV_RP36 = CSV.read(joinpath(case,\"Results_5/status.csv\"),DataFrame);\nOV_RP48 = CSV.read(joinpath(case,\"Results_6/status.csv\"),DataFrame);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Isolate the objective values from the data frame\nobj_val_tot = [1 OV_noTDR[!,3]; \n 4 OV_RP4[!,3];\n 8 OV_RP8[!,3];\n 12 OV_RP12[!,3]; \n 24 OV_RP24[!,3]; \n 36 OV_RP36[!,3]; \n 48 OV_RP48[!,3]]","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Take the absolute difference between the original objective value and the new ones\nobj_val_plot = [4 abs(OV_noTDR[!,3][1]-OV_RP4[!,3][1]); \n 8 abs(OV_noTDR[!,3][1]-OV_RP8[!,3][1]); \n 12 abs(OV_noTDR[!,3][1]-OV_RP12[!,3][1]);\n 24 abs(OV_noTDR[!,3][1]-OV_RP24[!,3][1]); \n 36 abs(OV_noTDR[!,3][1]-OV_RP36[!,3][1]); \n 48 abs(OV_noTDR[!,3][1]-OV_RP48[!,3][1])]","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Plot the differences as a function of number of representative periods\nplotlyjs()\nPlots.scatter(obj_val_plot[:,1],obj_val_plot[:,2],hover=obj_val_plot[:,2],legend=false,xticks=obj_val_plot[:,1],\n ylabel=\"|ObjValue[1] - ObjValue[x]|\",xlabel=\"Rep Periods\",title=\"Difference in Objective Values\")\nscatter!(twinx(),obj_val_plot[:,1],times,color=:red,markeralpha=.5,label=:\"Time\",legend=:topleft,\n yaxis=(label=\"Time\"))\nygrid!(:on, :dashdot, 0.1)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Here, we can see that while having very few representative periods produces an objective value that differs greatly from the orignal, once we reach around 12 representative periods the difference begins to taper out. Therefore, the original choice of 11 maximum periods in 1_three_zones decreases the run time of GenX significantly while while maintaining an objective value close to the original. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"It's important to note, however, that the difference does not always taper out, and for some systems you'll find that the error in objective value continues to decrease as the number of representative periods increases. There also is no way to know apriori what number of periods works.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Finally, let's set TDR to have 8 and 11 min/max periods again, and delete the TDR Results folder.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings[\"MinPeriods\"] = 8;\ntime_domain_reduction_settings[\"MaxPeriods\"] = 11;","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"rm(joinpath(case,\"TDR_results\", recursive=true))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"julia rm(joinpath(case,\"TDR_results\"), recursive=true) YAML.write_file(joinpath(case,\"settings/time_domain_reduction_settings.yml\"), time_domain_reduction_settings) folders = cd(readdir,case) for folder in folders if length(folder) >= 7 && folder[1:7] == \"results\" rm(\"example_systems/1_three_zones/\" * folder,recursive=true) end end","category":"page"},{"location":"User_Guide/methodofmorris_input/#Method_of_morris_range.csv-([Example](https://github.com/GenXProject/GenX/blob/main/Example_Systems/MethodofMorrisExample/OneZone/Method_of_morris_range.csv))","page":"Method of Morris Inputs","title":"Method_of_morris_range.csv (Example)","text":"","category":"section"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"This file contains the settings parameters required to run the Method of Morris algorithm in GenX. ","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"note: Note\nThis file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"Column Name Description\nResource This column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.\nZone Integer representing zone number where the resource is located.\nLower_bound Percentage lower deviation from the nominal value\nUpper_bound Percentage upper deviation from the nominal value\nParameter Column from the Generators_data.csv file containing uncertain parameters\nGroup Group the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined\np_steps Number of steps between upper and lower bound\ntotal_num_trajectory Total number of trakectories through the design matrix\nnum_trajectory Selected number of trajectories throigh the design matrix\nlen_design_mat Length of the design matrix\npolicy Name of the policy","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"Notes:","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"Upper and lower bounds are specified in terms of percentage deviation from the nominal value.\nPercentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lower_bound and Upper_bound must be identical.\nP_steps should at least be = 1%, i.e., Upper_bound – Lower_bound < p_steps\nP_steps for parameters in one group must be identical\nTotal_num_trajectory should be around 3 to 4 times the total number of uncertain parameters\nnum_trajectory should be approximately equal to the total number of uncertain parameters\nlen_design_mat should be 1.5 to 2 times the total number of uncertain parameters\nHigher number of num_trajectory and len_design_mat would lead to higher accuracy\nUpper and lower bounds should be specified for all the resources included in the Generators_data.csv file. If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.","category":"page"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/#Configure-multi-stage-inputs","page":"Configure multi-stage inputs","title":"Configure multi stage inputs","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/","page":"Configure multi-stage inputs","title":"Configure multi-stage inputs","text":"Modules = [GenX]\nPages = [\"configure_multi_stage_inputs.jl\"]","category":"page"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/#GenX.compute_overnight_capital_cost-Tuple{Dict, Array, Array, Array}","page":"Configure multi-stage inputs","title":"GenX.compute_overnight_capital_cost","text":"function compute_overnight_capital_cost(settings_d::Dict,inv_costs_yr::Array,crp::Array,tech_wacc::Array)\n\nThis function computes overnight capital costs incured within the model horizon, assuming that annualized costs to be paid after the model horizon are fully recoverable, and so are not included in the cost computation.\n\nFor each resource y in mathcalG with annualized investment cost AIC_y and capital recovery period CRP_y, overnight capital costs OCC_y are computed as follows:\n\nbeginaligned\n OCC_y = sum^min(CRP_yH)_i=1fracAIC_y(1+WACC_y)^i\nendaligned\n\nwhere WACC_y is the technology-specific weighted average cost of capital (set by the \"WACC\" field in the Generators_data.csv or Network.csv files), H is the number of years remaining between the start of the current model stage and the model horizon (the end of the final model stage) and CRP_y is the capital recovery period for technology y (specified in Generators_data.csv).\n\ninputs:\n\nsettings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\ninv_costs_yr - array object containing annualized investment costs.\ncrp - array object of capital recovery period values.\ntech_wacc - array object containing technology-specific weighted costs of capital.\n\nNOTE: The inv_costs_yr and crp arrays must be the same length; values with the same index in each array correspond to the same resource y in mathcalG.\n\nreturns: array object containing overnight capital costs, the discounted sum of annual investment costs incured within the model horizon.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/#GenX.configure_multi_stage_inputs-Tuple{Dict, Dict, Int64}","page":"Configure multi-stage inputs","title":"GenX.configure_multi_stage_inputs","text":"function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)\n\nThis function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:\n\nOvernight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.\nAnnualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by \"StageLength\" field in multi_stage_settings.yml).\nInternal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.\nWhen NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the \"Line_Max_Flow_Possible_MW\" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.\n\ninputs:\n\ninputs_d - dict object containing model inputs dictionary generated by load_inputs().\nsettings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\nNetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the \"NetworkExpansion\" field in genx_settings.yml.\n\nreturns: dictionary containing updated model inputs, to be used in the generate_model() method.\n\n\n\n\n\n","category":"method"},{"location":"User_Guide/model_output/#GenX-Outputs","page":"Model Outputs","title":"GenX Outputs","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"The table below summarizes the units of each output variable reported as part of the various CSV files produced after each model run. The reported units are also provided. If a result file includes time-dependent values, the value will not include the hour weight in it. An annual sum (\"AnnualSum\") column/row will be provided whenever it is possible (e.g., emissions.csv).","category":"page"},{"location":"User_Guide/model_output/#1-Default-output-files","page":"Model Outputs","title":"1 Default output files","text":"","category":"section"},{"location":"User_Guide/model_output/#1.1-capacity.csv","page":"Model Outputs","title":"1.1 capacity.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports optimal values of investment variables (except StartCap, which is an input)","category":"page"},{"location":"User_Guide/model_output/#Table-15:-Structure-of-the-capacity.csv-file","page":"Model Outputs","title":"Table 15: Structure of the capacity.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nStartCap Initial power capacity of each resource type in each zone; this is an input MW\nRetCap Retired power capacity of each resource type in each zone MW\nNewCap Installed capacity of each resource type in each zone MW\nEndCap Total power capacity of each resource type in each zone MW\nStartEnergyCap Initial energy capacity of each resource type in each zone; this is an input and applies only to storage tech. MWh\nRetEnergyCap Retired energy capacity of each resource type in each zone; applies only to storage tech. MWh\nNewEnergyCap Installed energy capacity of each resource type in each zone; applies only to storage tech. MWh\nEndEnergyCap Total installed energy capacity of each resource type in each zone; applies only to storage tech. MWh\nStartChargeCap Initial charging power capacity of STOR = 2 resource type in each zone; this is an input MW\nRetChargeCap Retired charging power capacity of STOR = 2 resource type in each zone MW\nNewChargeCap Installed charging capacity of each resource type in each zone MW\nEndChargeCap Total charging power capacity of each resource type in each zone MW","category":"page"},{"location":"User_Guide/model_output/#1.2-costs.csv","page":"Model Outputs","title":"1.2 costs.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports optimal objective function value and contribution of each term by zone.","category":"page"},{"location":"User_Guide/model_output/#Table-16:-Structure-of-the-costs.csv-file","page":"Model Outputs","title":"Table 16: Structure of the costs.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\ncTotal Total objective function value $\ncFix Total annualized investment and fixed operating & maintainenance (FOM) costs associated with all resources $\ncVar Total annual variable cost associated with all resources; includes fuel costs for thermal plants $\ncNSE Total annual cost of non-served energy $\ncStart Total annual cost of start-up of thermal power plants $\ncUnmetRsv Total annual cost of not meeting time-dependent operating reserve (spinning) requirements $\ncNetworkExp Total cost of network expansion $\ncEmissionsRevenue Total and zonal emissions revenue $\ncEmissionsCost Total an zonal emissions cost $","category":"page"},{"location":"User_Guide/model_output/#1.3-emissions.csv","page":"Model Outputs","title":"1.3 emissions.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports CO2 emissions by zone at each hour; an annual sum row will be provided. If any emission cap is present, emission prices each zone faced by each cap will be copied on top of this table with the following strucutre.","category":"page"},{"location":"User_Guide/model_output/#Table-17:-Structure-of-emission-prices-in-the-emissions.csv-file","page":"Model Outputs","title":"Table 17: Structure of emission prices in the emissions.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nCO2\\price Marginal CO2 abatement cost associated with constraint on maximum annual CO2 emissions; will be same across zones if CO2 emissions constraint is applied for the entire region and not zone-wise $/ tonne CO2.","category":"page"},{"location":"User_Guide/model_output/#1.4-nse.csv","page":"Model Outputs","title":"1.4 nse.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports non-served energy for every model zone, time step and cost-segment.","category":"page"},{"location":"User_Guide/model_output/#1.5-power.csv","page":"Model Outputs","title":"1.5 power.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports power discharged by each resource (generation, storage, demand response) in each model time step.","category":"page"},{"location":"User_Guide/model_output/#1.6-reliability.csv","page":"Model Outputs","title":"1.6 reliability.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.","category":"page"},{"location":"User_Guide/model_output/#1.7-prices.csv","page":"Model Outputs","title":"1.7 prices.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the load balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.","category":"page"},{"location":"User_Guide/model_output/#1.8-status.csv","page":"Model Outputs","title":"1.8 status.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports computational performance of the model and objective function related information.","category":"page"},{"location":"User_Guide/model_output/#Table-18:-Structure-of-the-status.csv-file","page":"Model Outputs","title":"Table 18: Structure of the status.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nStatus termination criteria (optimal, timelimit etc.). \nsolve Solve time including time for pre-solve seconds\nObjval Optimal objective function value $\nObjbound Best objective lower bound $\nFinalMIPGap Optimality gap at termination in case of a mixed-integer linear program (MIP gap); when using Gurobi, the lower bound and MIP gap is reported excluding constant terms (E.g. fixed cost of existing generators that cannot be retired) in the objective function and hence may not be directly usable. Fraction","category":"page"},{"location":"User_Guide/model_output/#1.9-NetRevenue.csv","page":"Model Outputs","title":"1.9 NetRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file summarizes the cost, revenue and profit for each generation technology for each region.","category":"page"},{"location":"User_Guide/model_output/#Table-19:-Stucture-of-the-NetRevenue.csv-file","page":"Model Outputs","title":"Table 19: Stucture of the NetRevenue.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nFixed_OM_cost_MW Fixed Operation and Maintenance cost of the MW capacity. $\nFixed_OM_cost_MWh Fixed Operation and Maintenance cost of the MWh capacity. Only applicable to energy storage. $\nVar_OM_cost_out Variable Operation and Maintenance cost of the power generation or discharge. $\nVar_OM_cost_in Variable Operation and Maintenance cost of the power charge/pumping. Only applicable to energy storage. $\nFuel_cost Fuel cost of the power generation. Only applicable to generation that burns fuel. $\nCharge_cost Cost of charging power (due to the payment for electricity) Only applicable to energy storage. $\nEmissionsCost Cost of buying emission credit. $\nStartCost Cost of generator start-up. $\nInv_cost_MW Cost of building MW capacity. $\nInv_cost_MWh Cost of building MWh capacity. $\nEnergyRevenue Revenue of generating power. $\nSubsidyRevenue Revenue of Min_Cap subsidy. $\nReserveMarginRevenue Revenue earned from capacity reserve margin constraints. $\nESRRevenue Revenue selling renewable/clean energy credits. $\nRevenue Total Revenue. $\nCost Total Cost. $\nProfit Revenue minus Cost. $","category":"page"},{"location":"User_Guide/model_output/#2-Settings-specific-outputs","page":"Model Outputs","title":"2 Settings-specific outputs","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This section includes the output files that GenX will print if corresponding function is specified in the Settings.","category":"page"},{"location":"User_Guide/model_output/#2.1-CapacityValue.csv","page":"Model Outputs","title":"2.1 CapacityValue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the time-dependent capacity value calculated for each generator. GenX will print this file only if the capacity reserve margin constraints are modeled through the setting file. Each row of the file (excluding the header) corresponds to a generator specified in the inputs. Each column starting from the t1 to the second last one stores the result of capacity obligation provided in each hour divided by the total capacity. Thus the number is unitless. If the capacity margin reserve is not binding for one hour, GenX will return zero. The last column specified the name of the corresponding capacity reserve constraint. Note that, if the user calculates the hour-weight-averaged capacity value for each generator using data of the binding hours, the result is what RTO/ISO call capacity credit.","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/#2.2-EnergyRevenue.csv","page":"Model Outputs","title":"2.2 EnergyRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the energy revenue in $ earned by each generator through injecting into the grid. Only annual sum values are available.","category":"page"},{"location":"User_Guide/model_output/#2.3-ChargingCost.csv","page":"Model Outputs","title":"2.3 ChargingCost.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the charging cost in $ of earned by each generator through withdrawing from the grid. Only annual sum values are available.","category":"page"},{"location":"User_Guide/model_output/#2.4-ReserveMargin.csv","page":"Model Outputs","title":"2.4 ReserveMargin.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the shadow prices of the capacity reserve margin constraints. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver, as described earlier. Each row (except the header) corresponds to a capacity reserve margin constraint, and each column corresponds to an time step. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.","category":"page"},{"location":"User_Guide/model_output/#2.5-ReserveMarginRevenue.csv","page":"Model Outputs","title":"2.5 ReserveMarginRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.","category":"page"},{"location":"User_Guide/model_output/#2.6-ESR_prices.csv","page":"Model Outputs","title":"2.6 ESR_prices.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the renewable/clean energy credit price of each modeled RPS/CES constraint. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. The unit is /MWh.","category":"page"},{"location":"User_Guide/model_output/#2.7-ESR_Revenue.csv","page":"Model Outputs","title":"2.7 ESR_Revenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.","category":"page"},{"location":"User_Guide/model_output/#2.8-SubsidyRevenue.csv","page":"Model Outputs","title":"2.8 SubsidyRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes subsidy revenue earned if a generator specified Min_Cap is provided in the input file. GenX will print this file only the shadow price can be obtained form the solver. Do not confuse this with the Minimum Capacity Carveout constraint, which is for a subset of generators, and a separate revenue term will be calculated in other files. The unit is $.","category":"page"},{"location":"Tutorials/Tutorials_intro/#GenX-Tutorials","page":"Tutorials Overview","title":"GenX Tutorials","text":"","category":"section"},{"location":"Tutorials/Tutorials_intro/","page":"Tutorials Overview","title":"Tutorials Overview","text":"Welcome to the GenX tutorials! In the following tutorials, we outline some important features of GenX and how to run them. All the tutorials are written in Julia and are available as Jupyter notebooks at the GenX-Tutorials repository.","category":"page"},{"location":"Tutorials/Tutorials_intro/","page":"Tutorials Overview","title":"Tutorials Overview","text":"Here is a list of the tutorials:","category":"page"},{"location":"Tutorials/Tutorials_intro/","page":"Tutorials Overview","title":"Tutorials Overview","text":"Tutorial 1: Configuring Settings\nTutorial 2: Network Visualization\nTutorial 3: K-Means and Time Domain Reduction\nTutorial 4: Model Generation\nTutorial 5: Solving the Model\nTutorial 6: Solver Settings","category":"page"},{"location":"User_Guide/model_input/#GenX-Inputs","page":"Model Inputs","title":"GenX Inputs","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"All input files are in CSV format. Running the GenX model requires a minimum of five mandatory input files:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Fuels_data.csv: specify fuel type, CO2 emissions intensity, and time-series of fuel prices.\nNetwork.csv: specify network topology, transmission fixed costs, capacity and loss parameters.\nDemand_data.csv: specify time-series of demand profiles for each model zone, weights for each time step, demand shedding costs, and optional time domain reduction parameters.\nGenerators_variability.csv: specify time-series of capacity factor/availability for each resource.\nGenerators_data.csv: specify cost and performance data for generation, storage and demand flexibility resources.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Additionally, the user may need to specify eight more settings-specific input files based on model configuration and type of scenarios of interest:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Operational_reserves.csv: specify operational reserve requirements as a function of demand and renewables generation and penalty for not meeting these requirements.\nEnergy_share_requirement.csv: specify regional renewable portfolio standard and clean energy standard style policies requiring minimum energy generation from qualifying resources.\nCO2_cap.csv: specify regional CO2 emission limits.\nCapacity_reserve_margin.csv: specify regional capacity reserve margin requirements.\nMinimum_capacity_requirement.csv: specify regional minimum technology capacity deployment requirements.\nVre_and_stor_data.csv: specify cost and performance data for co-located VRE and storage resources.\nVre_and_stor_solar_variability.csv: specify time-series of capacity factor/availability for each solar PV resource that exists for every co-located VRE and storage resource (in DC terms).\nVre_and_stor_wind_variability.csv: specify time-series of capacity factor/availability for each wind resource that exists for every co-located VRE and storage resource (in AC terms).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Note\nNames of the input files are case sensitive.","category":"page"},{"location":"User_Guide/model_input/#1-Mandatory-input-data","page":"Model Inputs","title":"1 Mandatory input data","text":"","category":"section"},{"location":"User_Guide/model_input/#1.1-Fuels_data.csv","page":"Model Inputs","title":"1.1 Fuels_data.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• First row: names of all fuels used in the model instance which should match the labels used in Fuel column in one of the resource .csv file in the resources folder. For renewable resources or other resources that do not consume a fuel, the name of the fuel is None.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second row: The second row specifies the CO2 emissions intensity of each fuel in tons/MMBtu (million British thermal units). Note that by convention, tons correspond to metric tonnes and not short tons (although as long as the user is internally consistent in their application of units, either can be used).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Remaining rows: Rest of the rows in this input file specify the time-series for prices for each fuel in /MMBtu. A constant price can be specified by entering the same value for all hours.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"** First column:** The first column in this file denotes, Time_index, represents the index of time steps in a model instance.","category":"page"},{"location":"User_Guide/model_input/#1.2-Network.csv","page":"Model Inputs","title":"1.2 Network.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This input file contains input parameters related to: 1) definition of model zones (regions between which transmission flows are explicitly modeled) and 2) definition of transmission network topology, existing capacity, losses and reinforcement costs. The following table describe each of the mandatory parameter inputs need to be specified to run an instance of the model, along with comments for the model configurations when they are needed.","category":"page"},{"location":"User_Guide/model_input/#Table-3:-Structure-of-the-Network.csv-file","page":"Model Inputs","title":"Table 3: Structure of the Network.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nSettings-specific Columns \nMultiple zone model \nNetwork_Lines Numerical index for each network line. The length of this column is counted but the actual values are not used.\nz* (Network map) OR StartZone, EndZone See below\nLine_Max_Flow_MW Existing capacity of the inter-regional transmission line.\nNetworkExpansion = 1 \nLine_Max_Reinforcement_MW Maximum allowable capacity addition to the existing transmission line.\nLine_Reinforcement_Cost_per_MWyr Cost of adding new capacity to the inter-regional transmission line.\nTrans_Loss_Segments = 1 \nLine_Loss_Percentage fractional transmission loss for each transmission line\nTrans_Loss_Segments > 1 \nOhms Line resistance in Ohms (used to calculate I^2R losses)\nkV Line voltage in kV (used to calculate I^2R losses)\nCapacityReserveMargin > 0 \nCapRes_* Eligibility of the transmission line for adding firm capacity to the capacity reserve margin constraint. * represents the number of the capacity reserve margin constraint.\n 1 = the transmission line is eligible for adding firm capacity to the region\n 0 = the transmission line is not eligible for adding firm capacity to the region\nDerateCapRes_* (0,1) value represents the derating of the firm transmission capacity for the capacity reserve margin constraint.\nCapResExcl_* (-1,1,0) = -1 if the designated direction of the transmission line is inbound to locational deliverability area (LDA) modeled by the capacity reserve margin constraint. = 1 if the designated direction of the transmission line is outbound from the LDA modeled by the capacity reserve margin constraint. Zero otherwise.\nMultiStage == 1 \nCapital_Recovery_Period Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for network transmission line expansion.\nLine_Max_Flow_Possible_MW Maximum possible line flow in the current model period. Overrides Line_Max_Reinforcement_MW, which is not used when performing multi-stage modeling.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"There are two interfaces implemented for specifying the network topology itself: a matrix interface and a list interface. Only one choice is permitted in a given file.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The list interface consists of a column for the lines start zone and one for the line's end zone. Here is a snippet of the Network.csv file for a map with three zones and two lines:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Network_Lines, Start_Zone, End_Zone,\n 1, 1, 2,\n 2, 1, 3,","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The matrix interface requires N columns labeled z1, z2, z3 ... zN, and L rows, one for each network line (or interregional path), with a 1 in the column corresponding to the 'start' zone and a -1 in the column corresponding to the 'end' zone for each line. Here is the same network map implemented as a matrix:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Network_Lines, z1, z2, z3,\n 1, 1, -1, 0,\n 2, 1, 0, -1,","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Note that in either case, positive flows indicate flow from start to end zone; negative flows indicate flow from end to start zone.","category":"page"},{"location":"User_Guide/model_input/#1.3-Demand_data.csv-(Load_data.csv)","page":"Model Inputs","title":"1.3 Demand_data.csv (Load_data.csv)","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file includes parameters to characterize model temporal resolution to approximate annual grid operations, electricity demand for each time step for each zone, and cost of load shedding. Note that GenX is designed to model hourly time steps. With some care and effort, finer (e.g. 15 minute) or courser (e.g. 2 hour) time steps can be modeled so long as all time-related parameters are scaled appropriately (e.g. time period weights, heat rates, ramp rates and minimum up and down times for generators, variable costs, etc).","category":"page"},{"location":"User_Guide/model_input/#Table-4:-Structure-of-the-Demand_data.csv-file","page":"Model Inputs","title":"Table 4: Structure of the Demand_data.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMandatory Columns \nVoll Value of lost load (also referred to as non-served energy) in /MWh.\nDemand_Segment Number of demand curtailment/unserved demand segments with different cost and capacity of curtailable demand for each segment. User-specified demand segments. Integer values starting with 1 in the first row. Additional segements added in subsequent rows.\nCost_of_Demand_Curtailment_per_MW Cost of non-served energy/demand curtailment (for each segment), reported as a fraction of value of the lost load (non-served demand). If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length equal to the length of Demand_Segment.\nMax_Demand_Curtailment Maximum time-dependent demand curtailable in each segment, reported as % of the demand in each zone and each period. If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length given by length of Demand_segment.\nTime_Index Index defining time step in the model.\nDemand_MW_z* Demand profile of a zone z* in MW; if multiple zones, this parameter will be a matrix with columns equal to number of zones (each column named appropriate zone number appended to parameter) and rows equal to number of time periods of grid operations being modeled.\nRep_Periods Number of representative periods (e.g. weeks, days) that are modeled to approximate annual grid operations. This is always a single entry. For a full-year model, this is 1.\nTimesteps_per_Rep_Period Number of timesteps per representative period (e.g. 168 if period is set as a week using hour-long time steps). This is always a single entry: all representative periods have the same length. For a full-year model, this entry is equal to the number of time steps.\nSub_Weights Number of annual time steps (e.g. hours) represented by each timestep in a representative period. The length of this column is equal to the number of representative periods. The sum of the elements should be equal to the total number of time steps in a model time horizon (e.g. 8760 hours if modeling 365 days or 8736 if modeling 52 weeks).","category":"page"},{"location":"User_Guide/model_input/#1.4-Resources-input-files","page":"Model Inputs","title":"1.4 Resources input files","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The resources folder contains the input files for each resource type. At the current version of GenX, the following resources are included in the model: ","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"thermal generators, specified in the Thermal.csv file,\nvariable renewable energy resources (VRE), specified in the VRE.csv file,\nreservoir hydro resources, specified in the Hydro.csv file,\nstorage resources, specified in the Storage.csv file,\nflexible demand resources, specified in the Flex_demand.csv file,\nmust-run resources, specified in the Must_run.csv file,\nelectrolyzers, specified in the Electrolyzer.csv file, and\nco-located VRE and storage resources, specified in the Vre_stor.csv file.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Each file contains cost and performance parameters for various generators and other resources included in the model formulation. The following table describes the mandatory columns in each of these files. Note that the column names are case insensitive.","category":"page"},{"location":"User_Guide/model_input/#Table-5a:-Mandatory-columns-in-all-resource-.csv-file","page":"Model Inputs","title":"Table 5a: Mandatory columns in all resource .csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource This column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.\nZone Integer representing zone number where the resource is located.\nTechnology type flags \nNew_Build {0, 1}, Flag for resource (storage, generation) eligibility for capacity expansion.\n New_Build = 1: eligible for capacity expansion.\n New_Build = 0: not eligible for capacity expansion.\nCan_Retire {0, 1}, Flag for resource (storage, generation) eligibility for retirement.\n Can_Retire = 1: eligible for retirement.\n Can_Retire = 0: not eligible for retirement.\nExisting technology capacity \nExisting_Cap_MW The existing capacity of a power plant in MW. Note that for co-located VRE-STOR resources, this capacity represents the existing AC grid connection capacity in MW.\nCapacity/Energy requirements \nMax_Cap_MW -1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the maximum AC grid connection capacity in MW.\nMin_Cap_MW -1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the minimum AC grid connection capacity in MW.\nCost parameters \nInv_Cost_per_MWyr Annualized capacity investment cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this annualized capacity investment cost pertains to the grid connection.\nFixed_OM_Cost_per_MWyr Fixed operations and maintenance cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this fixed operations and maintenance cost pertains to the grid connection.\nVar_OM_Cost_per_MWh Variable operations and maintenance cost of a technology (/MWh). Note that for co-located VRE-STOR resources, these costs apply to the AC generation sent to the grid from the entire site.\nTechnical performance parameters \nHeat_Rate_MMBTU_per_MWh Heat rate of a generator or MMBtu of fuel consumed per MWh of electricity generated for export (net of on-site consumption). The heat rate is the inverse of the efficiency: a lower heat rate is better. Should be consistent with fuel prices in terms of reporting on higher heating value (HHV) or lower heating value (LHV) basis.\nFuel Fuel needed for a generator. The names should match with the ones in the Fuels_data.csv.\nRequired for writing outputs \nregion Name of the model region\ncluster Number of the cluster when representing multiple clusters of a given technology in a given region.\nRequired if electrolyzer is included in the model \nQualifiedHydrogenSupply {0,1}, Indicates that generator or storage resources is eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint)\nRequired for retrofitting \nCan_Retrofit {0, 1}, Flag for resource (storage, generation) eligibility for retrofit.\n Can_Retrofit = 1: eligible for retrofit.\n Can_Retrofit = 0: not eligible for retrofit.\nRetrofit {0, 1}, Flag for resource retrofit technologies (i.e., retrofit options, e.g. CCS retrofit for coal plants).\n Retrofit = 1: is a retrofit technology.\n Retrofit = 0: is not a retrofit technology.\nRetrofit_Id Unique identifier to group retrofittable source technologies with retrofit options inside the same zone.\nRetrofit_Efficiency [0,1], Efficiency of the retrofit technology.","category":"page"},{"location":"User_Guide/model_input/#Table-5b:-Settings-specific-columns-in-all-resource-.csv-file","page":"Model Inputs","title":"Table 5b: Settings-specific columns in all resource .csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nModelingToGenerateAlternatives = 1 \nMGA Eligibility of the technology for Modeling To Generate Alternative (MGA) run.\n 1 = Technology is available for the MGA run.\n 0 = Technology is unavailable for the MGA run (e.g. storage technologies).\nResource_Type For the MGA run, we categorize all the resources in a few resource types. We then find maximally different generation portfolio based on these resource types. For example, existing solar and new solar resources could be represented by a resource type names Solar. Categorization of resources into resource types is user dependent.\nMaintenance data \nMAINT [0,1], toggles scheduled maintenance formulation.\nMaintenance_Duration (Positive integer, less than total length of simulation.) Duration of the maintenance period, in number of timesteps. Only used if MAINT=1.\nMaintenance_Cycle_Length_Years Length of scheduled maintenance cycle, in years. 1 is maintenance every year, 3 is every three years, etc. (Positive integer. Only used if MAINT=1.)\nMaintenance_Begin_Cadence Cadence of timesteps in which scheduled maintenance can begin. 1 means that a maintenance period can start in any timestep, 24 means it can start only in timesteps 1, 25, 49, etc. A larger number can decrease the simulation computational cost as it limits the optimizer's choices. (Positive integer, less than total length of simulation. Only used if MAINT=1.)\nCO2-related parameters required if any resources have nonzero CO2CaptureFraction \nCO2_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.\nCO2_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\nBiomass {0, 1}, Flag to indicate if generator uses biomass as feedstock (optional input column).\n Biomass = 0: Not part of set (default).\n Biomass = 1: Uses biomass as fuel.\nCCS_Disposal_Cost_per_Metric_Ton Cost associated with CCS disposal (/tCO2), including pipeline, injection and storage costs of CCS-equipped generators.","category":"page"},{"location":"User_Guide/model_input/#Table-6a:-Additional-columns-in-the-Thermal.csv-file","page":"Model Inputs","title":"Table 6a: Additional columns in the Thermal.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nModel {1, 2}, Flag to indicate membership in set of thermal resources (e.g. nuclear, combined heat and power, natural gas combined cycle, coal power plant)\n Model = 1: If the power plant relies on thermal energy input and subject unit commitment constraints/decisions if UCommit >= 1 (e.g. cycling decisions/costs/constraints).\n Model = 2: If the power plant relies on thermal energy input and is subject to simplified economic dispatch constraints (ramping limits and minimum output level but no cycling decisions/costs/constraints).\nMin_Power [0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.\nRamp_Up_Percentage [0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nRamp_Dn_Percentage [0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nPiecewiseFuelUsage-related parameters \nPWFU_Fuel_Usage_Zero_Load_MMBTU_per_h The fuel usage (MMBTU/h) for the first PWFU segemnt (y-intercept) at zero load.\nPWFU_Heat_Rate_MMBTU_per_MWh_*i The slope of fuel usage function of the segment i.\nPWFU_Load_Point_MW_*i The end of segment i (MW).\nMulti-fuel parameters \nMULTI_FUELS {0, 1}, Flag to indicate membership in set of thermal resources that can burn multiple fuels at the same time (e.g., natural gas combined cycle cofiring with hydrogen, coal power plant cofiring with natural gas.\n MULTI_FUELS = 0: Not part of set (default)\n MULTI_FUELS = 1: Resources that can use fuel blending.\nNum_Fuels Number of fuels that a multi-fuel generator (MULTIFUELS = 1) can use at the same time. The length of ['Fuel1', 'Fuel2', ...] should be equal to 'Num\\Fuels'. Each fuel will requires its corresponding heat rate, min cofire level, and max cofire level.\nFuel1 Frist fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.\nFuel2 Second fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.\nHeat1_Rate_MMBTU_per_MWh Heat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel1.\nHeat2_Rate_MMBTU_per_MWh Heat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel2.\nFuel1_Min_Cofire_Level The minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel1_Min_CofireLevel\\Start The minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.\nFuel1_Max_Cofire_Level The maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel1_Max_CofireLevel\\Start The maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.\nFuel2_Min_Cofire_Level The minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel2_Min_CofireLevel\\Start The minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.\nFuel2_Max_Cofire_Level The maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel2_Max_CofireLevel\\Start The maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.","category":"page"},{"location":"User_Guide/model_input/#Table-6b:-Settings-specific-columns-in-the-Thermal.csv-file","page":"Model Inputs","title":"Table 6b: Settings-specific columns in the Thermal.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nUCommit >= 1 The following settings apply only to thermal plants with unit commitment constraints\nUp_Time Minimum amount of time a resource has to stay in the committed state.\nDown_Time Minimum amount of time a resource has to remain in the shutdown state.\nStart_Cost_per_MW Cost per MW of nameplate capacity to start a generator (/MW per start). Multiplied by the number of generation units (each with a pre-specified nameplate capacity) that is turned on.\nStart_Fuel_MMBTU_per_MW Startup fuel use per MW of nameplate capacity of each generator (MMBtu/MW per start).\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-7a:-Additional-columns-in-the-Vre.csv-file","page":"Model Inputs","title":"Table 7a: Additional columns in the Vre.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nNum_VRE_bins Number of resource availability profiles considered for each VRE resource per zone. This parameter is used to decide the number of capacity investment decision variables related to a single variable renewable energy technology in each zone.\n Num_VRE_bins = 1: using a single resource availability profile per technology per zone. 1 capacity investment decision variable and 1 generator RID tracking technology power output (and in each zone).\n Num_VRE_bins > 1: using multiple resource availability profiles per technology per zone. Num_VRE_bins capacity investment decision variables and 1 generator RID used to define technology power output at each time step (and in each zone). Example: Suppose we are modeling 3 bins of wind profiles for each zone. Then include 3 rows with wind resource names as Wind_1, Wind_2, and Wind_3 and a corresponding increasing sequence of RIDs. Set Num_VRE_bins for the generator with smallest RID, Wind_1, to be 3 and set Num_VRE_bins for the other rows corresponding to Wind_2 and Wind_3, to be zero. By setting Num_VRE_bins for Wind_2 and Wind_3, the model eliminates the power outputs variables for these generators. The power output from the technology across all bins is reported in the power output variable for the first generator. This allows for multiple bins without significantly increasing number of model variables (adding each bin only adds one new capacity variable and no operational variables). See documentation for curtailable_variable_renewable() for more.","category":"page"},{"location":"User_Guide/model_input/#Table-6b:-Settings-specific-columns-in-the-Vre.csv-file","page":"Model Inputs","title":"Table 6b: Settings-specific columns in the Vre.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-7a:-Additional-columns-in-the-Hydro.csv-file","page":"Model Inputs","title":"Table 7a: Additional columns in the Hydro.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMin_Power [0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.\nRamp_Up_Percentage [0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nRamp_Dn_Percentage [0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nHydro_Energy_to_Power_Ratio The rated number of hours of reservoir hydro storage at peak discharge power output. (hours).\nLDS {0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.\n LDS = 0: Not part of set (default)\n LDS = 1: Long duration storage resources","category":"page"},{"location":"User_Guide/model_input/#Table-7b:-Settings-specific-columns-in-the-Hydro.csv-file","page":"Model Inputs","title":"Table 7b: Settings-specific columns in the Hydro.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-8a:-Additional-columns-in-the-Storage.csv-file","page":"Model Inputs","title":"Table 8a: Additional columns in the Storage.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nModel {0, 1, 2}, Flag to indicate membership in set of storage resources and designate which type of storage resource formulation to employ.\n Model = 0: Not part of set (default)\n Model = 1: Discharging power capacity and energy capacity are the investment decision variables; symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage).\n Model = 2: Discharging, charging power capacity and energy capacity are investment variables; asymmetric charge and discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nLDS {0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.\n LDS = 0: Not part of set (default)\n LDS = 1: Long duration storage resources\nSelf_Disch [0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs.\nEff_Up [0,1], Efficiency of charging storage.\nEff_Down [0,1], Efficiency of discharging storage.\nMin_Duration Specifies the minimum ratio of installed energy to discharged power capacity that can be installed (hours).\nMax_Duration Specifies the maximum ratio of installed energy to discharged power capacity that can be installed (hours).\nExisting technology capacity \nExisting_Cap_MWh The existing capacity of storage in MWh where Model = 1 or Model = 2.\nExisting_Charge_Cap_MW The existing charging capacity for resources where Model = 2.\nCapacity/Energy requirements \nMax_Cap_MWh -1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.\nMax_Charge_Cap_MW -1 (default) – no limit on maximum charge capacity of the resource. If non-negative, represents maximum allowed charge capacity (in MW) of the resource with Model = 2.\nMin_Cap_MWh -1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.\nMin_Charge_Cap_MW -1 (default) – no limit on minimum charge capacity of the resource. If non-negative, represents minimum allowed charge capacity (in MW) of the resource with Model = 2.\nCost parameters \nInv_Cost_per_MWhyr Annualized investment cost of the energy capacity for a storage technology (/MW/year), applicable to either Model = 1 or Model = 2.\nInv_Cost_Charge_per_MWyr Annualized capacity investment cost for the charging portion of a storage technology with Model = 2 (/MW/year).\nFixed_OM_Cost_per_MWhyr Fixed operations and maintenance cost of the energy component of a storage technology (/MWh/year).\nFixed_OM_Cost_Charge_per_MWyr Fixed operations and maintenance cost of the charging component of a storage technology of type Model = 2.\nVar_OM_Cost_per_MWhIn Variable operations and maintenance cost of the charging aspect of a storage technology with Model = 2. Otherwise 0 (/MWh).","category":"page"},{"location":"User_Guide/model_input/#Table-8b:-Settings-specific-columns-in-the-Storage.csv-file","page":"Model Inputs","title":"Table 8b: Settings-specific columns in the Storage.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-9:-Additional-columns-in-the-Flex_demand.csv-file","page":"Model Inputs","title":"Table 9: Additional columns in the Flex_demand.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMax_Flexible_Demand_Delay Maximum number of hours that demand can be deferred or delayed (hours).\nMax_Flexible_Demand_Advance Maximum number of hours that demand can be scheduled in advance of the original schedule (hours).\nFlexible_Demand_Energy_Eff [0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand (hours). For example, one may need to pre-cool a building more than normal to advance demand.\nCost parameters \nVar_OM_Cost_per_MWhIn Variable operations and maintenance costs associated with flexible demand deferral. Otherwise 0 (/MWh).","category":"page"},{"location":"User_Guide/model_input/#Table-10:-Additional-columns-in-the-Electrolyzer.csv-file","page":"Model Inputs","title":"Table 10: Additional columns in the Electrolyzer.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nHydrogenMWhPer_Tonne Electrolyzer efficiency in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced (MWh/t)\nElectrolyzerMinkt Minimum annual quantity of hydrogen that must be produced by electrolyzer in kilotonnes (kt)\nHydrogenPricePer_Tonne Price (or value) of hydrogen per metric tonne (/t)\nMin_Power [0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.\nRamp_Up_Percentage [0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nRamp_Dn_Percentage [0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Note\nCheck Qualified_Hydrogen_Supply column in table 5a if electrolyzers are included in the model. This column is used to indicate which resources are eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Each co-located VRE and storage resource can be easily configured to contain either a co-located VRE-storage resource, standalone VRE resource (either wind, solar PV, or both), or standalone storage resource.","category":"page"},{"location":"User_Guide/model_input/#Table-11a:-Additional-columns-in-the-Vre_stor.csv-file","page":"Model Inputs","title":"Table 11a: Additional columns in the Vre_stor.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nTechnology type flags \nSOLAR {0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a solar PV component.\n SOLAR = 0: Not part of set (default)\n SOLAR = 1: If the co-located VRE-storage resource can produce solar PV energy.\nWIND {0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a wind component.\n WIND = 0: Not part of set (default)\n WIND = 1: If the co-located VRE-storage resource can produce wind energy.\nSTORDCDISCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharge behind the meter and through the inverter (DC).\n STORDCDISCHARGE = 0: Not part of set (default)\n STORDCDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCDISCHARGE = 1, STORDCCHARGE = 1.\n STORDCDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nSTORDCCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge through the inverter (DC).\n STORDCCHARGE = 0: Not part of set (default)\n STORDCCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCCHARGE = 1, STORDCDISCHARGE = 1.\n STORDCCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nSTORACDISCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharges AC.\n STORACDISCHARGE = 0: Not part of set (default)\n STORACDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACDISCHARGE = 1, STORACCHARGE = 1.\n STORACDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nSTORACCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge AC.\n STORACCHARGE = 0: Not part of set (default)\n STORACCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACCHARGE = 1, STORACDISCHARGE = 1.\n STORACCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nLDSVRESTOR {0, 1}, Flag to indicate the co-located VRE-storage resources eligible for long duration storage constraints with inter period linkage (e.g., reservoir hydro, hydrogen storage).\n LDSVRESTOR = 0: Not part of set (default)\n LDSVRESTOR = 1: Long duration storage resources\nExisting technology capacity \nExisting_Cap_MW The existing AC grid connection capacity in MW.\nExisting_Cap_MWh The existing capacity of storage in MWh.\nExisting_Cap_Inverter_MW The existing capacity of co-located VRE-STOR resource's inverter in MW (AC).\nExisting_Cap_Solar_MW The existing capacity of co-located VRE-STOR resource's solar PV in MW (DC).\nExisting_Cap_Wind_MW The existing capacity of co-located VRE-STOR resource's wind in MW (AC).\nExisting_Cap_Discharge_DC_MW The existing discharge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_DISCHARGE = 2.\nExisting_Cap_Charge_DC_MW The existing charge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_CHARGE = 2.\nExisting_Cap_Discharge_AC_MW The existing discharge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_AC_DISCHARGE = 2.\nExisting_Cap_Charge_AC_MW The existing charge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_DC_CHARGE = 2.\nCapacity/Energy requirements \nMax_Cap_MW -1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed AC grid connection capacity in MW of the resource.\nMax_Cap_MWh -1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity of storage in MWh.\nMin_Cap_MW -1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed AC grid connection capacity in MW.\nMin_Cap_MWh -1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity of storage in MWh.\nMax_Cap_Inverter_MW -1 (default) – no limit on maximum inverter capacity of the resource. If non-negative, represents maximum allowed inverter capacity (in MW AC) of the resource.\nMax_Cap_Solar_MW -1 (default) – no limit on maximum solar PV capacity of the resource. If non-negative, represents maximum allowed solar PV capacity (in MW DC) of the resource.\nMax_Cap_Wind_MW -1 (default) – no limit on maximum wind capacity of the resource. If non-negative, represents maximum allowed wind capacity (in MW AC) of the resource.\nMax_Cap_Discharge_DC_MW -1 (default) – no limit on maximum DC discharge capacity of the resource. If non-negative, represents maximum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.\nMax_Cap_Charge_DC_MW -1 (default) – no limit on maximum DC charge capacity of the resource. If non-negative, represents maximum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.\nMax_Cap_Discharge_AC_MW -1 (default) – no limit on maximum AC discharge capacity of the resource. If non-negative, represents maximum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.\nMax_Cap_Charge_AC_MW -1 (default) – no limit on maximum AC charge capacity of the resource. If non-negative, represents maximum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.\nMin_Cap_Inverter_MW -1 (default) – no limit on minimum inverter capacity of the resource. If non-negative, represents minimum allowed inverter capacity (in MW AC) of the resource.\nMin_Cap_Solar_MW -1 (default) – no limit on minimum solar PV capacity of the resource. If non-negative, represents minimum allowed solar PV capacity (in MW DC) of the resource.\nMin_Cap_Wind_MW -1 (default) – no limit on minimum wind capacity of the resource. If non-negative, represents minimum allowed wind capacity (in MW AC) of the resource.\nMin_Cap_Discharge_DC_MW -1 (default) – no limit on minimum DC discharge capacity of the resource. If non-negative, represents minimum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.\nMin_Cap_Charge_DC_MW -1 (default) – no limit on minimum DC charge capacity of the resource. If non-negative, represents minimum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.\nMin_Cap_Discharge_AC_MW -1 (default) – no limit on minimum AC discharge capacity of the resource. If non-negative, represents minimum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.\nMin_Cap_Charge_AC_MW -1 (default) – no limit on minimum AC charge capacity of the resource. If non-negative, represents minimum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.\nCost parameters \nInv_Cost_per_MWyr Annualized capacity investment cost of the grid connection (/MW/year).\nInv_Cost_per_MWhyr Annualized investment cost of the energy capacity for the co-located storage resource (/MW/year)\nFixed_OM_Cost_per_MWyr Fixed operations and maintenance cost of the grid connection (/MW/year).\nFixed_OM_Cost_per_MWhyr Fixed operations and maintenance cost of the energy component of the co-located storage resource. (/MWh/year).\nInv_Cost_Inverter_per_MWyr Annualized capacity investment cost of the inverter component (/MW-AC/year).\nInv_Cost_Solar_per_MWyr Annualized capacity investment cost of the solar PV component (/MW-DC/year).\nInv_Cost_Wind_per_MWyr Annualized capacity investment cost of the wind component (/MW-AC/year).\nInv_Cost_Discharge_DC_per_MWyr Annualized capacity investment cost for the discharging portion of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).\nInv_Cost_Charge_DC_per_MWyr Annualized capacity investment cost for the charging portion of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).\nInv_Cost_Discharge_AC_per_MWyr Annualized capacity investment cost for the discharging portion of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).\nInv_Cost_Charge_AC_per_MWyr Annualized capacity investment cost for the charging portion of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).\nFixed_OM_Inverter_Cost_per_MWyr Fixed operations and maintenance cost of the inverter component (/MW-AC/year).\nFixed_OM_Solar_Cost_per_MWyr Fixed operations and maintenance cost of the solar PV component (/MW-DC/year).\nFixed_OM_Wind_Cost_per_MWyr Fixed operations and maintenance cost of the wind component (/MW-AC/year).\nFixed_OM_Cost_Discharge_DC_per_MWyr Fixed operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).\nFixed_OM_Cost_Charge_DC_per_MWyr Fixed operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).\nFixed_OM_Cost_Discharge_AC_per_MWyr Fixed operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).\nFixed_OM_Cost_Charge_AC_per_MWyr Fixed operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).\nVar_OM_Cost_per_MWh_Solar Variable operations and maintenance cost of the solar PV component (multiplied by the inverter efficiency for AC terms) (/MWh).\nVar_OM_Cost_per_MWh_Wind Variable operations and maintenance cost of the wind component (/MWh).\nVar_OM_Cost_per_MWh_Discharge_DC Variable operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (multiplied by the inverter efficiency for AC terms) (/MWh).\nVar_OM_Cost_per_MWh_Charge_DC Variable operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (divided by the inverter efficiency for AC terms) (/MWh).\nVar_OM_Cost_per_MWh_Discharge_AC Variable operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MWh).\nVar_OM_Cost_per_MWh_Charge_AC Variable operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MWh).\nTechnical performance parameters \nSelf_Disch [0,1], The power loss of storage component of each resource per hour (fraction loss per hour).\nEtaInverter [0,1], Inverter efficiency representing losses from converting DC to AC power and vice versa for each technology\nInverterRatioSolar -1 (default) - no required ratio between solar PV capacity built to inverter capacity built. If non-negative, represents the ratio of solar PV capacity built to inverter capacity built.\nInverterRatioWind -1 (default) - no required ratio between wind capacity built to grid connection capacity built. If non-negative, represents the ratio of wind capacity built to grid connection capacity built.\nPower_to_Energy_AC The power to energy conversion for the storage component for AC discharging/charging of symmetric storage resources.\nPower_to_Energy_DC The power to energy conversion for the storage component for DC discharging/charging of symmetric storage resources.\nEff_Up_DC [0,1], Efficiency of DC charging storage – applies to storage technologies (all STOR types).\nEff_Down_DC [0,1], Efficiency of DC discharging storage – applies to storage technologies (all STOR types).\nEff_Up_AC [0,1], Efficiency of AC charging storage – applies to storage technologies (all STOR types).\nEff_Down_AC [0,1], Efficiency of AC discharging storage – applies to storage technologies (all STOR types).","category":"page"},{"location":"User_Guide/model_input/#Table-11b:-Settings-specific-columns-in-the-Vre_stor.csv-file","page":"Model Inputs","title":"Table 11b: Settings-specific columns in the Vre_stor.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Policy-related-columns-for-all-resources","page":"Model Inputs","title":"Policy-related columns for all resources","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"In addition to the files described above, the resources folder contains the following files that are used to specify policy-related parameters for specific resources: ","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Resource_energy_share_requirement.csv\nResource_minimum_capacity_requirement.csv\nResource_maximum_capacity_requirement.csv\nResource_capacity_reserve_margin.csv","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Note\nThese files are optional and can be omitted if no policy-related parameters are specified in the settings file. Also, not all the resources need to be included in these files, only those for which the policy applies.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The following table describes the columns in each of these four files.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"warning: Warning\nThe first column of each file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in the policy files is not important.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if EnergyShareRequirement > 0 in the settings file. * corresponds to the ith row of the file Energy_share_requirement.csv. ","category":"page"},{"location":"User_Guide/model_input/#Table-12:-Energy-share-requirement-policy-parameters","page":"Model Inputs","title":"Table 12: Energy share requirement policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nESR_* Flag to indicate which resources are considered for the Energy Share Requirement constraint.\n 1- included\n 0- excluded\nco-located VRE-STOR resources only \nESRVreStor_* Flag to indicate which resources are considered for the Energy Share Requirement constraint.\n 1- included\n 0- excluded","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if MinCapReq = 1 in the settings file. * corresponds to the ith row of the file Minimum_capacity_requirement.csv. ","category":"page"},{"location":"User_Guide/model_input/#Table-13:-Minimum-capacity-requirement-policy-parameters","page":"Model Inputs","title":"Table 13: Minimum capacity requirement policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nMinCap\\* Flag to indicate which resources are considered for the Minimum Capacity Requirement constraint.\nco-located VRE-STOR resources only \nMinCapSolar_* Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Minimum Technology Carveout constraint.\nMinCapWind_* Eligibility of resources with a wind component to participate in Minimum Technology Carveout constraint (AC terms).\nMinCapStor_* Eligibility of resources with a storage component to participate in Minimum Technology Carveout constraint (discharge capacity in AC terms).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if MaxCapReq = 1 in the settings file. * corresponds to the ith row of the file Maximum_capacity_requirement.csv.","category":"page"},{"location":"User_Guide/model_input/#Table-14:-Maximum-capacity-requirement-policy-parameters","page":"Model Inputs","title":"Table 14: Maximum capacity requirement policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nMaxCap\\* Flag to indicate which resources are considered for the Maximum Capacity Requirement constraint.\nco-located VRE-STOR resources only \nMaxCapSolar_* Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Maximum Technology Carveout constraint.\nMaxCapWind_* Eligibility of resources with a wind component to participate in Maximum Technology Carveout constraint (AC terms).\nMaxCapStor_* Eligibility of resources with a storage component to participate in Maximum Technology Carveout constraint (discharge capacity in AC terms).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if CapacityReserveMargin > 0 in the settings file. * corresponds to the ith row of the file Capacity_reserve_margin.csv.","category":"page"},{"location":"User_Guide/model_input/#Table-15:-Capacity-reserve-margin-policy-parameters","page":"Model Inputs","title":"Table 15: Capacity reserve margin policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nEligibleCapRes_* Fraction of the resource capacity eligible for contributing to the capacity reserve margin constraint (e.g. derate factor).","category":"page"},{"location":"User_Guide/model_input/#Additional-module-related-columns-for-all-resources","page":"Model Inputs","title":"Additional module-related columns for all resources","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"In addition to the files described above, the resources folder can contain additional files that are used to specify attributes for specific resources and modules. Currently, the following files are supported:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Resource_multistage_data.csv: mandatory if MultiStage = 1 in the settings file","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"warning: Warning\nThe first column of each additional module file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in these files is not important.","category":"page"},{"location":"User_Guide/model_input/#Table-16:-Multistage-parameters","page":"Model Inputs","title":"Table 16: Multistage parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"warning: Warning\nThis file is mandatory if MultiStage = 1 in the settings file.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nCapital_Recovery_Period Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.\nLifetime Lifetime (in years) used for determining endogenous retirements of newly built capacity. Note that the same lifetime is used for each component of a co-located VRE-STOR resource.\nMin_Retired_Cap_MW Minimum required discharge capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.\nMin_Retired_Energy_Cap_MW Minimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing energy capacity. Note that for co-located VRE-STOR resources, this value pertains to the storage component.\nMin_Retired_Charge_Cap_MW Minimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing charge capacity.\nContribute_Min_Retirement {0, 1}, Flag to indicate whether the (retrofitting) resource can contribute to the minimum retirement requirement.\nco-located VRE-STOR resources only \nCapital_Recovery_Period_DC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the inverter component.\nCapital_Recovery_Period_Solar Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the solar PV component.\nCapital_Recovery_Period_Wind Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the wind component.\nCapital_Recovery_PeriodDischargeDC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge DC component when STOR_DC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeDC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge DC component when STOR_DC_CHARGE = 2.\nCapital_Recovery_PeriodDischargeAC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge AC component when STOR_AC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeAC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge AC component when STOR_AC_CHARGE = 2.\nMin_Retired_Cap_Inverter_MW Minimum required inverter capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_Solar_MW Minimum required solar capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_Wind_MW Minimum required wind capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_DischargeDC\\MW Minimum required discharge capacity retirements in the current model period for storage resources with STOR_DC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_ChargeDC\\MW Minimum required charge capacity retirements in the current model period for storage resources with STOR_DC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_DischargeAC\\MW Minimum required discharge capacity retirements in the current model period for storage resources with STOR_AC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_ChargeAC\\MW Minimum required charge capacity retirements in the current model period for storage resources with STOR_AC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nWACC_DC The line-specific weighted average cost of capital for the inverter component.\nWACC_Solar The line-specific weighted average cost of capital for the solar PV component.\nWACC_Wind The line-specific weighted average cost of capital for the wind component.\nWACC_Discharge_DC The line-specific weighted average cost of capital for the discharging DC storage component with STOR_DC_DISCHARGE = 2.\nWACC_Charge_DC The line-specific weighted average cost of capital for the charging DC storage component with STOR_DC_CHARGE = 2.\nWACC_Discharge_AC The line-specific weighted average cost of capital for the discharging AC storage component with STOR_AC_DISCHARGE = 2.\nWACC_Charge_AC The line-specific weighted average cost of capital for the charging AC storage component with STOR_AC_CHARGE = 2.","category":"page"},{"location":"User_Guide/model_input/#1.5-Generator_variability.csv","page":"Model Inputs","title":"1.5 Generator_variability.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the time-series of capacity factors / availability of each resource included in the resource .csv file in the resources folder for each time step (e.g. hour) modeled.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the resource .csv file in the resources folder in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in the resource .csv file must be unique. Note that for Hydro reservoir resources (i.e. Hydro.csv), values in this file correspond to inflows (in MWhs) to the hydro reservoir as a fraction of installed power capacity, rather than hourly capacity factor. Note that for co-located VRE and storage resources, solar PV and wind resource profiles should not be located in this file but rather in separate variability files (these variabilities can be in the Generators_variability.csv if time domain reduction functionalities will be utilized because the time domain reduction functionalities will separate the files after the clustering is completed).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"|Self_Disch |[0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs. Note that for co-located VRE-STOR resources, this value applies to the storage component of each resource.| |Min_Power |[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Up_Percentage |[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Dn_Percentage |[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Eff_Up |[0,1], Efficiency of charging storage – applies to storage technologies (all STOR types except co-located storage resources).| |Eff_Down |[0,1], Efficiency of discharging storage – applies to storage technologies (all STOR types except co-located storage resources). |","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"|Min_Duration |Specifies the minimum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Duration |Specifies the maximum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Flexible_Demand_Delay |Maximum number of hours that demand can be deferred or delayed. Applies to resources with FLEX type 1 (hours). | |Max_Flexible_Demand_Advance |Maximum number of hours that demand can be scheduled in advance of the original schedule. Applies to resources with FLEX type 1 (hours). | |Flexible_Demand_Energy_Eff |[0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand. Applies to resources with FLEX type 1 (hours). For example, one may need to pre-cool a building more than normal to advance demand. |","category":"page"},{"location":"User_Guide/model_input/#1.6-Vre_and_stor_solar_variability.csv","page":"Model Inputs","title":"1.6 Vre_and_stor_solar_variability.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the time-series of capacity factors / availability of the solar PV component (DC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• first column: The first column contains the time index of each row (starting in the second row) from 1 to N.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique. ","category":"page"},{"location":"User_Guide/model_input/#1.7-Vre_and_stor_wind_variability.csv","page":"Model Inputs","title":"1.7 Vre_and_stor_wind_variability.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the time-series of capacity factors / availability of the wind component (AC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique. ","category":"page"},{"location":"User_Guide/model_input/#2.-Optional-inputs-files","page":"Model Inputs","title":"2. Optional inputs files","text":"","category":"section"},{"location":"User_Guide/model_input/#2.1-Operational_reserves.csv","page":"Model Inputs","title":"2.1 Operational_reserves.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file includes parameter inputs needed to model time-dependent procurement of regulation and spinning reserves. This file is needed if OperationalReserves flag is activated in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-7:-Structure-of-the-Operational_reserves.csv-file","page":"Model Inputs","title":"Table 7: Structure of the Operational_reserves.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nReg_Req_Percent_Demand [0,1], Regulation requirement as a percent of time-dependent demand; here demand is the total across all model zones.\nReg_Req_Percent_VRE [0,1], Regulation requirement as a percent of time-dependent wind and solar generation (summed across all model zones).\nRsv_Req_Percent_Demand [0,1], Spinning up or contingency reserve requirement as a percent of time-dependent demand (which is summed across all zones).\nRsv_Req_Percent_VRE [0,1], Spinning up or contingency reserve requirement as a percent of time-dependent wind and solar generation (which is summed across all zones).\nUnmet_Rsv_Penalty_Dollar_per_MW Penalty for not meeting time-dependent spinning reserve requirement (/MW per time step).\nDynamic_Contingency Flags to include capacity (generation or transmission) contingency to be added to the spinning reserve requirement.\nDynamic_Contingency = 1: contingency set to be equal to largest installed thermal unit (only applied when UCommit = 1).\n = 2: contingency set to be equal to largest committed thermal unit each time period (only applied when UCommit = 1).\nStatic_Contingency_MW A fixed static contingency in MW added to reserve requirement. Applied when UCommit = 1 and DynamicContingency = 0, or when UCommit = 2. Contingency term not included in operating reserve requirement when this value is set to 0 and DynamicContingency is not active.","category":"page"},{"location":"User_Guide/model_input/#2.2-Energy_share_requirement.csv","page":"Model Inputs","title":"2.2 Energy_share_requirement.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains inputs specifying minimum energy share requirement policies, such as Renewable Portfolio Standard (RPS) or Clean Energy Standard (CES) policies. This file is needed if parameter EnergyShareRequirement has a non-zero value in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Note: this file should use the same region name as specified in the the resource .csv file (inside the Resource).","category":"page"},{"location":"User_Guide/model_input/#Table-8:-Structure-of-the-Energy_share_requirement.csv-file","page":"Model Inputs","title":"Table 8: Structure of the Energy_share_requirement.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nRegion_description Region name\nNetwork_zones zone number represented as z*\nESR_* [0,1], Energy share requirements as a share of zonal demand (calculated on an annual basis). * represents the number of the ESR constraint, given by the number of ESR_* columns in the Energy_share_requirement.csv file.","category":"page"},{"location":"User_Guide/model_input/#2.3-CO2_cap.csv","page":"Model Inputs","title":"2.3 CO2_cap.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains inputs specifying CO2 emission limits policies (e.g. emissions cap and permit trading programs). This file is needed if CO2Cap flag is activated in the YAML file genx_settings.yml. CO2Cap flag set to 1 represents mass-based (tCO2 ) emission target. CO2Cap flag set to 2 is specified when emission target is given in terms of rate (tCO2/MWh) and is based on total demand met. CO2Cap flag set to 3 is specified when emission target is given in terms of rate (tCO2 /MWh) and is based on total generation.","category":"page"},{"location":"User_Guide/model_input/#Table-9:-Structure-of-the-CO2_cap.csv-file","page":"Model Inputs","title":"Table 9: Structure of the CO2_cap.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nRegion_description Region name\nNetwork_zones zone number represented as z*\nCO_2_Cap_Zone_* If a zone is eligible for the emission limit constraint, then this column is set to 1, else 0.\nCO_2_Max_tons_MWh_* Emission limit in terms of rate\nCO_2_Max_Mtons_* Emission limit in absolute values, in Million of tons\n where in the above inputs, * represents the number of the emission limit constraints. For example, if the model has 2 emission limit constraints applied separately for 2 zones, the above CSV file will have 2 columns for specifying emission limit in terms on rate: CO_2_Max_tons_MWh_1 and CO_2_Max_tons_MWh_2.","category":"page"},{"location":"User_Guide/model_input/#2.4-Capacity_reserve_margin.csv","page":"Model Inputs","title":"2.4 Capacity_reserve_margin.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the regional capacity reserve margin requirements. This file is needed if parameter CapacityReserveMargin has a non-zero value in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Note: this file should use the same region name as specified in the resource .csv file (inside the Resource).","category":"page"},{"location":"User_Guide/model_input/#Table-10:-Structure-of-the-Capacity_reserve_margin.csv-file","page":"Model Inputs","title":"Table 10: Structure of the Capacity_reserve_margin.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nRegion_description Region name\nNetwork_zones zone number represented as z*\nCapRes_* [0,1], Capacity reserve margin requirements of a zone, reported as a fraction of demand","category":"page"},{"location":"User_Guide/model_input/#2.5-Minimum_capacity_requirement.csv","page":"Model Inputs","title":"2.5 Minimum_capacity_requirement.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the minimum capacity carve-out requirement to be imposed (e.g. a storage capacity mandate or offshore wind capacity mandate). This file is needed if the MinCapReq flag has a non-zero value in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-11:-Structure-of-the-Minimum_capacity_requirement.csv-file","page":"Model Inputs","title":"Table 11: Structure of the Minimum_capacity_requirement.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMinCapReqConstraint Index of the minimum capacity carve-out requirement.\nConstraint_Description Names of minimum capacity carve-out constraints; not to be read by model, but used as a helpful notation to the model user.\nMin_MW minimum capacity requirement [MW]","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.","category":"page"},{"location":"User_Guide/model_input/#2.6-Maximum_capacity_requirement.csv","page":"Model Inputs","title":"2.6 Maximum_capacity_requirement.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This contains the maximum capacity limits to be imposed (e.g. limits on total deployment of solar, wind, or batteries in the system as a whole or in certain collections of zones). It is required if the MaxCapReq flag has a non-zero value in genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-12:-Structure-of-the-Maximum_capacity_requirement.csv-file","page":"Model Inputs","title":"Table 12: Structure of the Maximum_capacity_requirement.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMaxCapReqConstraint Index of the maximum capacity limit.\nConstraint_Description Names of maximum capacity limit; not to be read by model, but used as a helpful notation to the model user.\nMax_MW maximum capacity limit [MW]","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.","category":"page"},{"location":"User_Guide/model_input/#2.7-Method_of_morris_range.csv","page":"Model Inputs","title":"2.7 Method_of_morris_range.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the settings parameters required to run the Method of Morris algorithm in GenX. This file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-13:-Structure-of-the-Method_of_morris_range.csv-file","page":"Model Inputs","title":"Table 13: Structure of the Method_of_morris_range.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource This column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand/loads.\nZone Integer representing zone number where the resource is located.\nLower_bound Percentage lower deviation from the nominal value\nUpper_bound Percentage upper deviation from the nominal value\nParameter Column from the resource .csv file (inside the Resource) containing uncertain parameters\nGroup Group the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined\np_steps Number of steps between upper and lower bound\ntotal_num_trajectory Total number of trakectories through the design matrix\nnum_trajectory Selected number of trajectories throigh the design matrix\nlen_design_mat Length of the design matrix\npolicy Name of the policy","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Notes\nUpper and lower bounds are specified in terms of percentage deviation from the nominal value.\nPercentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lowerbound and Upperbound must be identical\nP_steps should at least be = 1\\%, i.e., Upper_bound – Lower_bound p_steps\nP_steps for parameters in one group must be identical\nTotal_num_trajectory should be around 3 to 4 times the total number of uncertain parameters\nnum_trajectory should be approximately equal to the total number of uncertain parameters\nlen_design_mat should be 1.5 to 2 times the total number of uncertain parameters\nHigher number of num_trajectory and lendesignmat would lead to higher accuracy\nUpper and lower bounds should be specified for all the resources included in the resource .csv file (inside the Resource). If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.","category":"page"},{"location":"Model_Reference/methodofmorris/#Method-of-Morris","page":"Method of Morris","title":"Method of Morris","text":"","category":"section"},{"location":"Model_Reference/methodofmorris/","page":"Method of Morris","title":"Method of Morris","text":"Modules = [GenX]\nPages = [\"method_of_morris.jl\"]","category":"page"},{"location":"Model_Reference/methodofmorris/#GenX.MatSpread","page":"Method of Morris","title":"GenX.MatSpread","text":"morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER)\n\nWe apply the Method of Morris developed by Morris, M., 1991 in order to identify the input parameters that produce the largest change on total system cost. Method of Morris falls under the simplest class of one-factor-at-a-time (OAT) screening techniques. It assumes l levels per input factor and generates a set of trajectories through the input space. As such, the Method of Morris generates a grid of uncertain model input parameters, x_i i=1 k,, where the range x_i^- x_i^+ of each uncertain input parameter i is split into l intervals of equal length. Each trajectory starts at different realizations of input parameters chosen at random and are built by successively selecting one of the inputs randomly and moving it to an adjacent level. These trajectories are used to estimate the mean and the standard deviation of each input parameter on total system cost. A high estimated mean indicates that the input parameter is important; a high estimated standard deviation indicates important interactions between that input parameter and other inputs.\n\n\n\n\n\n","category":"type"},{"location":"User_Guide/model_configuration/#Model-settings-parameters","page":"Model Configuration","title":"Model settings parameters","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"The first step in configuring a GenX model is to specify the model settings parameters. These parameters are specified in a genx_settings.yml file inside a settings folder which must be located in the current working directory. Settings include those related to model structure, solution strategy and outputs, policy constraints, and others. In particular:","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Model structure related settings parameters affect the formulation of the model constraints and objective function. \nComputational performance related parameters affect the accuracy of the solution.\nPolicy related parameters specify the policy type and policy goal. \nNetwork related parameters specify settings related to transmission network expansion and losses.","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Note that all settings parameters are case sensitive.","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"(Optional) The user can also select the output files that they want to export using the output_settings.yml file. This file containes a list of yes/no options for each output file, and should be located in the settings folder. By default, if output_settings.yml is not included, GenX will export all output files. ","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"The following tables summarize the model settings parameters and their default/possible values.","category":"page"},{"location":"User_Guide/model_configuration/#1.-Model-structure-related-settings-parameters","page":"Model Configuration","title":"1. Model structure related settings parameters","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nUCommit Select technical resolution of of modeling thermal generators.\n 0 = no unit commitment.\n 1 = unit commitment with integer clustering.\n 2 = unit commitment with linearized clustering.\nOperationalReserves Flag for modeling operational reserves .\n 0 = No operational reserves considered.\n 1 = Consider regulation (primary) and spinning (secondary) reserves.\nStorageLosses Flag to account for storage related losses.\n 0 = VRE and CO2 constraints DO NOT account for energy lost.\n 1 = constraints account for energy lost.\nTimeDomainReduction 1 = Use time domain reduced inputs available in the folder with the name defined by settings parameter TimeDomainReductionFolder. If such a folder does not exist or it is empty, time domain reduction will reduce the input data and save the results there.\n 0 = Use the data in the main case folder; do not perform clustering.\nTimeDomainReductionFolder Name of the folder insie the current working directory where time domain reduced input data is stored.\nVirtualChargeDischargeCost Hypothetical cost of charging and discharging storage resources (in /MWh).","category":"page"},{"location":"User_Guide/model_configuration/#2.-Solution-strategy","page":"Model Configuration","title":"2. Solution strategy","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nParameterScale Flag to turn on parameter scaling wherein demand, capacity and power variables defined in GW rather than MW. This flag aides in improving the computational performance of the model.\n 1 = Scaling is activated.\n 0 = Scaling is not activated.\nMultiStage Model multiple planning stages\n 1 = Model multiple planning stages as specified in multi_stage_settings.yml\n 0 = Model single planning stage\nModelingToGenerateAlternatives Modeling to Generate Alternative Algorithm. For details, see here\n 1 = Use the algorithm.\n 0 = Do not use the algorithm.\nModelingtoGenerateAlternativeSlack value used to define the maximum deviation from the least-cost solution as a part of Modeling to Generate Alternative Algorithm. Can take any real value between 0 and 1.\nMethodofMorris Method of Morris algorithm\n 1 = Use the algorithm.\n 0 = Do not use the algorithm.","category":"page"},{"location":"User_Guide/model_configuration/#3.-Policy-related","page":"Model Configuration","title":"3. Policy related","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nCO2Cap Flag for specifying the type of CO2 emission limit constraint.\n 0 = no CO2 emission limit\n 1 = mass-based emission limit constraint\n 2 = demand + rate-based emission limit constraint\n 3 = generation + rate-based emission limit constraint\nEnergyShareRequirement Flag for specifying regional renewable portfolio standard (RPS) and clean energy standard policy (CES) related constraints.\n Default = 0 (No RPS or CES constraints).\n 1 = activate energy share requirement related constraints.\nCapacityReserveMargin Flag for Capacity Reserve Margin constraints.\n Default = 0 (No Capacity Reserve Margin constraints)\n 1 = activate Capacity Reserve Margin related constraints\nMinCapReq Minimum technology carve out requirement constraints.\n 1 = if one or more minimum technology capacity constraints are specified\n 0 = otherwise\nMaxCapReq Maximum system-wide technology capacity limit constraints.\n 1 = if one or more maximum technology capacity constraints are specified\n 0 = otherwise","category":"page"},{"location":"User_Guide/model_configuration/#4.-Network-related","page":"Model Configuration","title":"4. Network related","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nNetworkExpansion Flag for activating or deactivating inter-regional transmission expansion.\n 1 = active\n 0 = modeling single zone or for multi-zone problems in which inter regional transmission expansion is not allowed.\nTrans_Loss_Segments Number of segments to use in piece-wise linear approximation of losses.\n 1: linear\n >=2: piece-wise quadratic","category":"page"},{"location":"User_Guide/model_configuration/#5.-Outputs","page":"Model Configuration","title":"5. Outputs","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nPrintModel Flag for printing the model equations as .lp file.\n 1 = including the model equation as an output\n 0 = the model equation won't be included as an output\nWriteShadowPrices Get the optimal values of dual variables of various model related constraints, including to estimate electricity prices, stored value of energy and the marginal CO2 prices.\nWriteOutputs Flag for writing the model outputs with hourly resolution or just the annual sum.\n \"full\" = write the model outputs with hourly resolution.\n \"annual\" = write only the annual sum of the model outputs.","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"The next step in configuring a GenX model is to specify the solver settings parameters using a [solver_name]_settings.yml file inside the settings folder. The solver settings parameters are solver specific and are described in the following section.","category":"page"},{"location":"Model_Reference/Resources/storage_asymmetric/#Storage-Asymmetric","page":"Storage Asymmetric","title":"Storage Asymmetric","text":"","category":"section"},{"location":"Model_Reference/Resources/storage_asymmetric/","page":"Storage Asymmetric","title":"Storage Asymmetric","text":"Modules = [GenX]\nPages = [\"storage_asymmetric.jl\"]","category":"page"},{"location":"Model_Reference/Resources/storage_asymmetric/#GenX.storage_asymmetric!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Asymmetric","title":"GenX.storage_asymmetric!","text":"storage_asymmetric!(EP::Model, inputs::Dict, setup::Dict)\n\nSets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/storage_asymmetric/#GenX.storage_asymmetric_operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Asymmetric","title":"GenX.storage_asymmetric_operational_reserves!","text":"storage_asymmetric_operational_reserves!(EP::Model, inputs::Dict)\n\nSets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/storage/#Storage","page":"Storage","title":"Storage","text":"","category":"section"},{"location":"Model_Reference/Resources/storage/","page":"Storage","title":"Storage","text":"GenX.storage!","category":"page"},{"location":"Model_Reference/Resources/storage/#GenX.storage!","page":"Storage","title":"GenX.storage!","text":"storage!(EP::Model, inputs::Dict, setup::Dict)\n\nA wide range of energy storage devices (all o in mathcalO) can be modeled in GenX, using one of two generic storage formulations: (1) storage technologies with symmetric charge and discharge capacity (all o in mathcalO^sym), such as Lithium-ion batteries and most other electrochemical storage devices that use the same components for both charge and discharge; and (2) storage technologies that employ distinct and potentially asymmetric charge and discharge capacities (all o in mathcalO^asym), such as most thermal storage technologies or hydrogen electrolysis/storage/fuel cell or combustion turbine systems.\n\nIf a capacity reserve margin is modeled, variables for virtual charge, Pi^CRM_ozt, and virtual discharge, Theta^CRM_ozt, are created to represent \tcontributions that a storage device makes to the capacity reserve margin without actually generating power. (This functionality can be turned off with the parameter StorageVirtualDischarge in the GenX settings file.) These represent power that the storage device could \thave discharged or consumed if called upon to do so, based on its available state of charge. Importantly, a dedicated set of variables (those of the form Pi^CRM_ozt Theta^CRM_ozt) \tand constraints are created to ensure that any virtual contributions to the capacity reserve margin could be made as actual charge/discharge if necessary without \taffecting system operations in any other timesteps. If a capacity reserve margin is not modeled, all related variables are fixed at 0. The overall contribution \tof storage devices to the system's capacity reserve margin in timestep t is equal to sum_y in mathcalO epsilon_yzp^CRM times left(Theta_yzt + Theta^CRM_ozt - Pi^CRM_ozt - Pi_yzt right), \tand includes both actual and virtual charge and discharge.\n\nbeginaligned\n\t Pi_ozt + Pi^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\n\t Pi_ozt + Pi^CRM_ozt + Theta_ozt + Theta^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\nendaligned\n\nStorage with symmetric charge and discharge capacity For storage technologies with symmetric charge and discharge capacity (all o in mathcalO^sym), charge rate, Pi_ozt, and virtual charge rate, Pi^CRM_ozt, are jointly constrained by the total installed power capacity, Omega_oz. Since storage resources generally represent a `cluster' of multiple similar storage devices of the same type/cost in the same zone, GenX permits storage resources to simultaneously charge and discharge (as some units could be charging while others discharge), with the simultaenous sum of charge, Pi_ozt, discharge, Theta_ozt, virtual charge, Pi^CRM_ozt, and virtual discharge, Theta^CRM_ozt, also limited by the total installed power capacity, Delta^total_oz. These two constraints are as follows:\n\nbeginaligned\n Pi_ozt + Pi^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\n Pi_ozt + Pi^CRM_ozt + Theta_ozt + Theta^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\nendaligned\n\nThese constraints are created with the function storage_symmetric!() in storage_symmetric.jl. If reserves are modeled, the following two constraints replace those above:\n\nbeginaligned\n Pi_ozt + Pi^CRM_ozt + f^charge_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\n Pi_ozt + Pi^CRM_ozt + f^charge_ozt + Theta_ozt + Theta^CRM_ozt + f^discharge_ozt + r^discharge_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT \nendaligned\n\nwhere f^charge_ozt is the contribution of storage resources to frequency regulation while charging, f^discharge_ozt is the contribution of storage resources to frequency regulation while discharging, and r^discharge_ozt is the contribution of storage resources to upward reserves while discharging. Note that as storage resources can contribute to regulation and reserves while either charging or discharging, the proxy variables f^charge_ozt f^discharge_ozt and r^charge_ozt r^discharge_ozt are created for storage resources where the total contribution to regulation and reserves, f_ozt r_ozt is the sum of the proxy variables. These constraints are created with the function storage_symmetric_operational_reserves!() in storage_symmetric.jl. Storage with asymmetric charge and discharge capacity For storage technologies with asymmetric charge and discharge capacities (all o in mathcalO^asym), charge rate, Pi_ozt, is constrained by the total installed charge capacity, Delta^total charge_oz, as follows:\n\nbeginaligned\n\t Pi_ozt + Pi^CRM_ozt leq Delta^total charge_oz quad forall o in mathcalO^asym z in mathcalZ t in mathcalT\nendaligned\n\nThese constraints are created with the function storage_asymmetric() in storage_asymmetric.jl. If reserves are modeled, the above constraint is replaced by the following:\n\nbeginaligned\n\t Pi_ozt + Pi^CRM_ozt + f^charge_ozt leq Delta^total charge_oz quad forall o in mathcalO^asym z in mathcalZ t in mathcalT\nendaligned\n\nwhere f^+_y=ozt is the contribution of storage resources to frequency regulation while charging. These constraints are created with the function storage_symmetric_operational_reserves!() in storage_asymmetric.jl. All storage resources The following constraints apply to all storage resources, o in mathcalO, regardless of whether the charge/discharge capacities are symmetric or asymmetric. The following two constraints track the state of charge of the storage resources at the end of each time period, relating the volume of energy stored at the end of the time period, Gamma_ozt, to the state of charge at the end of the prior time period, Gamma_ozt-1, the charge and discharge decisions in the current time period, Pi_ozt Theta_ozt, and the self discharge rate for the storage resource (if any), eta_oz^loss. The first of these two constraints enforces storage inventory balance for interior time steps (t in mathcalT^interior), while the second enforces storage balance constraint for the initial time step (t in mathcalT^start).\n\nbeginaligned\n\t Gamma_ozt =Gamma_ozt-1 - frac1eta_oz^dischargeTheta_ozt + eta_oz^chargePi_ozt - eta_oz^lossGamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^interior\n\t Gamma_ozt =Gamma_ozt+tau^period-1 - frac1eta_oz^dischargeTheta_ozt + eta_oz^chargePi_ozt - eta_oz^lossGamma_ozt+tau^period-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^start\nendaligned\n\nIf a capacity reserve margin is modeled, then the following constraints track the relationship between the virtual charge, Pi^CRM_ozt, and virtual discharge, Theta^CRM_ozt, variables and a third variable, Gamma^CRM_ozt, representing the amount of state of charge that must be held in reserve to enable these virtual capacity reserve margin contributions, ensuring that the storage device could deliver its pledged capacity if called upon to do so without affecting its operations in other timesteps. Gamma^CRM_ozt is tracked similarly to the devices overall state of charge based on its value in the previous timestep and the virtual charge and discharge in the current timestep. Unlike the regular state of charge, virtual discharge Theta^CRM_ozt increases Gamma^CRM_ozt (as more charge must be held in reserve to support more virtual discharge), and Pi^CRM_ozt reduces Gamma^CRM_ozt.\n\nbeginaligned\n\t Gamma^CRM_ozt =Gamma^CRM_ozt-1 + frac1eta_oz^dischargeTheta^CRM_ozt - eta_oz^chargePi^CRM_ozt - eta_oz^lossGamma^CRM_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^interior\n\t Gamma^CRM_ozt =Gamma^CRM_ozt+tau^period-1 + frac1eta_oz^dischargeTheta^CRM_ozt - eta_oz^chargePi^CRM_ozt - eta_oz^lossGamma^CRM_ozt+tau^period-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^start\nendaligned\n\nThe energy held in reserve, Gamma^CRM_ozt, also acts as a lower bound on the overall state of charge Gamma_ozt. This ensures that the storage device cannot use state of charge that would not have been available had it been called on to actually contribute its pledged virtual discharge at some earlier timestep. This relationship is described by the following equation:\n\nbeginaligned\n\t Gamma_ozt geq Gamma^CRM_ozt \nendaligned\n\nWhen modeling the entire year as a single chronological period with total number of time steps of tau^period, storage inventory in the first time step is linked to storage inventory at the last time step of the period representing the year. Alternatively, when modeling the entire year with multiple representative periods, this constraint relates storage inventory in the first timestep of the representative period with the inventory at the last time step of the representative period, where each representative period is made of tau^period time steps. In this implementation, energy exchange between representative periods is not permitted. When modeling representative time periods, GenX enables modeling of long duration energy storage which tracks state of charge (and state of charge held in reserve, if a capacity reserve margin is being modeled) between representative periods enable energy to be moved throughout the year. If there is more than one representative period and LDS has been enabled for resources in Generators.csv, this function calls long_duration_storage() in long_duration_storage.jl to enable this feature. The next constraint limits the volume of energy stored at any time, Gamma_ozt, to be less than the installed energy storage capacity, Delta^total energy_oz. Finally, the maximum combined discharge and virtual discharge rate for storage resources, Pi_ozt + Pi^CRM_ozt, is constrained to be less than the discharge power capacity, Omega_ozt or the state of charge at the end of the last period, Gamma_ozt-1, whichever is less.\n\nbeginaligned\n\t Gamma_ozt leq Delta^total energy_oz quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt + Theta^CRM_ozt leq Delta^total_oz quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt + Theta^CRM_ozt leq Gamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nThe above constraints are established in storage_all!() in storage_all.jl. If reserves are modeled, two pairs of proxy variables f^charge_ozt f^discharge_ozt and r^charge_ozt r^discharge_ozt are created for storage resources, to denote the contribution of storage resources to regulation or reserves while charging or discharging, respectively. The total contribution to regulation and reserves, f_ozt r_ozt is then the sum of the proxy variables:\n\nbeginaligned\n\t f_ozt = f^charge_ozt + f^dicharge_ozt quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t r_ozt = r^charge_ozt + r^dicharge_ozt quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nThe total storage contribution to frequency regulation (f_ozt) and reserves (r_ozt) are each limited specified fraction of installed discharge power capacity (upsilon^reg_yz upsilon^rsv_yz), reflecting the maximum ramp rate for the storage resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nbeginaligned\n\tf_yzt leq upsilon^reg_yz times Delta^total_yz\n\thspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT \n\tr_yz t leq upsilon^rsv_yztimes Delta^total_yz\n\thspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT\n\tendaligned\n\nWhen charging, reducing the charge rate is contributing to upwards reserve and frequency regulation as it drops net demand. As such, the sum of the charge rate plus contribution to regulation and reserves up must be greater than zero. Additionally, the discharge rate plus the contribution to regulation must be greater than zero.\n\nbeginaligned\n\t Pi_ozt - f^charge_ozt - r^charge_ozt geq 0 quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt - f^discharge_ozt geq 0 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nAdditionally, when reserves are modeled, the maximum charge rate, virtual charge rate, and contribution to regulation while charging can be no greater than the available energy storage capacity, or the difference between the total energy storage capacity, Delta^total energy_oz, and the state of charge at the end of the previous time period, Gamma_ozt-1, while accounting for charging losses eta_oz^charge. Note that for storage to contribute to reserves down while charging, the storage device must be capable of increasing the charge rate (which increase net load).\n\nbeginaligned\n\t eta_oz^charge times (Pi_ozt + Pi^CRM_ozt + f^charge_ozt) leq Delta^energy total_oz - Gamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nFinally, the constraints on maximum discharge rate are replaced by the following, to account for capacity contributed to regulation and reserves:\n\nbeginaligned\n\t Theta_ozt + Theta^CRM_ozt + f^discharge_ozt + r^discharge_ozt leq Delta^total_oz quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt + Theta^CRM_ozt + f^discharge_ozt + r^discharge_ozt leq Gamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nThe above reserve related constraints are established by storage_all_operational_reserves!() in storage_all.jl\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/#Multi-stage-investment-planning","page":"Multi-Stage Modeling Introduction","title":"Multi-stage investment planning","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"Added in 0.3","category":"page"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"GenX can be used to study the long-term evolution of the power system across multiple investment stages, in the following two ways:","category":"page"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here. This algorithm splits up a multi-stage investment planning problem into multiple, single-period sub-problems. Each period is solved iteratively as a separate linear program sub-problem (“forward pass”), and information from future periods is shared with past periods (“backwards pass”) so that investment decisions made in subsequent iterations reflect the contributions of present-day investments to future costs. The decomposition algorithm adapts previous nested Benders methods by handling integer and continuous state variables, although at the expense of losing its finite convergence property due to potential duality gap.\nThe user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as \"myopic\" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.","category":"page"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"More information on this feature can be found in the section Multi-stage setup.","category":"page"},{"location":"Model_Reference/write_outputs/#Functions-for-Writing-the-Different-Results/Outputs-to-Separate-Files","page":"Outputs Functions","title":"Functions for Writing the Different Results/Outputs to Separate Files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_outputs.jl\", \"choose_output_dir.jl\", \"dftranspose.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_annual-Tuple{AbstractString, DataFrames.DataFrame}","page":"Outputs Functions","title":"GenX.write_annual","text":"write_annual(fullpath::AbstractString, dfOut::DataFrame)\n\nInternal function for writing annual outputs. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.write_fulltimeseries-Tuple{AbstractString, Matrix{Float64}, DataFrames.DataFrame}","page":"Outputs Functions","title":"GenX.write_fulltimeseries","text":"write_fulltimeseries(fullpath::AbstractString, dataOut::Matrix{Float64}, dfOut::DataFrame)\n\nInternal function for writing full time series outputs. This function wraps the instructions for creating the full time series output files. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.write_outputs-Tuple{JuMP.Model, AbstractString, Dict, Dict}","page":"Outputs Functions","title":"GenX.write_outputs","text":"write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nFunction for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.choose_output_dir-Tuple{String}","page":"Outputs Functions","title":"GenX.choose_output_dir","text":"path = choose_output_dir(pathinit)\n\nAvoid overwriting (potentially important) existing results by appending to the directory name\n\nChecks if the suggested output directory already exists. While yes, it appends _1, _2, etc till an unused name is found\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.dftranspose-Tuple{DataFrames.DataFrame, Bool}","page":"Outputs Functions","title":"GenX.dftranspose","text":"df = dftranspose(df::DataFrame, withhead::Bool)\n\nReturns a transpose of a Dataframe.\n\nFIXME: This is for DataFrames@0.20.2, as used in GenX. Versions 0.21+ could use stack and unstack to make further changes while retaining the order\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Status","page":"Outputs Functions","title":"Write Status","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_status.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_status-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_status","text":"write_status(path::AbstractString, inputs::Dict, EP::Model)\n\nFunction for writing the final solve status of the optimization problem solved.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-CO_2-Cap","page":"Outputs Functions","title":"Write CO_2 Cap","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_co2_cap","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_co2_cap","page":"Outputs Functions","title":"GenX.write_co2_cap","text":"write_co2_cap(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting carbon price associated with carbon cap constraints.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Costs","page":"Outputs Functions","title":"Write Costs","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_costs.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_costs-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_costs","text":"write_costs(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the costs pertaining to the objective function (fixed, variable O&M etc.).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Fuel-Consumption","page":"Outputs Functions","title":"Write Fuel Consumption","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_fuel_consumption","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_fuel_consumption","page":"Outputs Functions","title":"GenX.write_fuel_consumption","text":"write_fuel_consumption(path::AbstractString, inputs::Dict, setup::Dict, EP::Model).\n\nWrite fuel consumption of each power plant. \n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Emissions","page":"Outputs Functions","title":"Write Emissions","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_emissions.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_emissions-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_emissions","text":"write_emissions(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting time-dependent CO_2 emissions by zone.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacities","page":"Outputs Functions","title":"Write Capacities","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_capacity.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_capacity-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_capacity","text":"write_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model))\n\nFunction for writing the diferent capacities for the different generation technologies (starting capacities or, existing capacities, retired capacities, and new-built capacities).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacity-Value-#-TODO:-add-it","page":"Outputs Functions","title":"Write Capacity Value # TODO: add it","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_capacity_value.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.capacity_reserve_margin_price-Tuple{JuMP.Model, Dict, Dict, Int64}","page":"Outputs Functions","title":"GenX.capacity_reserve_margin_price","text":"capacity_reserve_margin_price(EP::Model,\n inputs::Dict,\n setup::Dict,\n capres_zone::Int)::Vector{Float64}\n\nMarginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.\n\nReturns a vector, with units of $/MW\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacity-Factors","page":"Outputs Functions","title":"Write Capacity Factors","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_capacityfactor.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_capacityfactor-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_capacityfactor","text":"write_capacityfactor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the capacity factor of different resources. For co-located VRE-storage resources, this value is calculated if the site has either or both a solar PV or wind resource.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Charge-Values","page":"Outputs Functions","title":"Write Charge Values","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_charge.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_charge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_charge","text":"write_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the charging energy values of the different storage technologies.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Non-served-energy","page":"Outputs Functions","title":"Write Non-served-energy","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_nse.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_nse-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_nse","text":"write_nse(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting non-served energy for every model zone, time step and cost-segment.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Storage-State-of-Charge","page":"Outputs Functions","title":"Write Storage State of Charge","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_storage.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_storage-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_storage","text":"write_storage(path::AbstractString, inputs::Dict,setup::Dict, EP::Model)\n\nFunction for writing the capacities of different storage technologies, including hydro reservoir, flexible storage tech etc.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Storage-Dual","page":"Outputs Functions","title":"Write Storage Dual","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_storagedual.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_storagedual-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_storagedual","text":"write_storagedual(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting dual of storage level (state of charge) balance of each resource in each time step.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Power","page":"Outputs Functions","title":"Write Power","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_power.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_power-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_power","text":"write_power(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the different values of power generated by the different technologies in operation.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Curtailment","page":"Outputs Functions","title":"Write Curtailment","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_curtailment.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_curtailment-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_curtailment","text":"write_curtailment(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the curtailment values of the different variable renewable resources (both standalone and \tco-located).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Prices","page":"Outputs Functions","title":"Write Prices","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_price.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.locational_marginal_price-Tuple{JuMP.Model, Dict, Dict}","page":"Outputs Functions","title":"GenX.locational_marginal_price","text":"locational_marginal_price(EP::Model, inputs::Dict, setup::Dict)\n\nMarginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.\n\nReturns a matrix of size (T, Z).\nValues have units of $/MWh\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.write_price-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_price","text":"write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the power balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Reliability","page":"Outputs Functions","title":"Write Reliability","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_reliability.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_reliability-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_reliability","text":"write_reliability(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Energy-Revenue","page":"Outputs Functions","title":"Write Energy Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_energy_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_energy_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_energy_revenue","text":"write_energy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing energy revenue from the different generation technologies.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Subsidy-Revenue","page":"Outputs Functions","title":"Write Subsidy Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_subsidy_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_subsidy_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_subsidy_revenue","text":"write_subsidy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting subsidy revenue earned if a generator specified Min_Cap is provided in the input file, or if a generator is subject to a Minimum Capacity Requirement constraint. The unit is $.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Operating-Reserve-and-Regulation-Revenue","page":"Outputs Functions","title":"Write Operating Reserve and Regulation Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_operating_reserve_price_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_operating_reserve_regulation_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_operating_reserve_regulation_revenue","text":"write_operating_reserve_regulation_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting the operating reserve and regulation revenue earned by generators listed in the input file. GenX will print this file only when operating reserve and regulation are modeled and the shadow price can be obtained from the solver. The revenues are calculated as the operating reserve and regulation contributions in each time step multiplied by the corresponding shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all operating reserve and regulation constraints. As a reminder, GenX models the operating reserve and regulation at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacity-Revenue","page":"Outputs Functions","title":"Write Capacity Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_reserve_margin_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_reserve_margin_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_reserve_margin_revenue","text":"write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Energy-Share-Requirement-Revenue","page":"Outputs Functions","title":"Write Energy Share Requirement Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_esr_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_esr_revenue-Tuple{AbstractString, Dict, Dict, DataFrames.DataFrame, DataFrames.DataFrame, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_esr_revenue","text":"write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPower::DataFrame, dfESR::DataFrame, EP::Model)\n\nFunction for reporting the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Net-Revenue","page":"Outputs Functions","title":"Write Net Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_net_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_net_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame, DataFrames.DataFrame}","page":"Outputs Functions","title":"GenX.write_net_revenue","text":"write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model, dfCap::DataFrame, dfESRRev::DataFrame, dfResRevenue::DataFrame, dfChargingcost::DataFrame, dfPower::DataFrame, dfEnergyRevenue::DataFrame, dfSubRevenue::DataFrame, dfRegSubRevenue::DataFrame, dfVreStor::DataFrame, dfOpRegRevenue::DataFrame, dfOpRsvRevenue::DataFrame)\n\nFunction for writing net revenue of different generation technologies.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Co-Located-VRE-and-Storage-files","page":"Outputs Functions","title":"Write Co-Located VRE and Storage files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_vre_stor\nGenX.write_vre_stor_capacity\nGenX.write_vre_stor_charge\nGenX.write_vre_stor_discharge","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor","page":"Outputs Functions","title":"GenX.write_vre_stor","text":"write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage specific files.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor_capacity","page":"Outputs Functions","title":"GenX.write_vre_stor_capacity","text":"write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage capacities.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor_charge","page":"Outputs Functions","title":"GenX.write_vre_stor_charge","text":"write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage charging decision variables/expressions.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor_discharge","page":"Outputs Functions","title":"GenX.write_vre_stor_discharge","text":"write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage discharging decision variables/expressions.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Multi-stage-files","page":"Outputs Functions","title":"Write Multi-stage files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_multi_stage_costs\nGenX.write_multi_stage_stats\nGenX.write_multi_stage_settings\nGenX.write_multi_stage_network_expansion\nGenX.write_multi_stage_capacities_charge\nGenX.write_multi_stage_capacities_energy","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_costs","page":"Outputs Functions","title":"GenX.write_multi_stage_costs","text":"write_multi_stage_costs(outpath::String, settings_d::Dict)\n\nThis function writes the file costs_multi_stage.csv to the Results directory. This file contains variable, fixed, startup, network expansion, unmet reserve, and non-served energy costs discounted to year zero.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_stats","page":"Outputs Functions","title":"GenX.write_multi_stage_stats","text":"writemultistagestats(outpath::String, statsd::Dict)\n\nThis function writes the file stats_multi_stage.csv. to the Results directory. This file contains the runtime, upper bound, lower bound, and relative optimality gap for each iteration of the DDP algorithm.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_settings","page":"Outputs Functions","title":"GenX.write_multi_stage_settings","text":"write_multi_stage_settings(outpath::AbstractString, settings_d::Dict)\n\nFunction for writing the multi-stage settings file to the output path for future reference.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_network_expansion","page":"Outputs Functions","title":"GenX.write_multi_stage_network_expansion","text":"write_multi_stage_network_expansion(outpath::String, settings_d::Dict)\n\nThis function writes the file network_expansion_multi_stage.csv to the Results directory. This file contains new transmission capacities for each modeled transmission line for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_capacities_charge","page":"Outputs Functions","title":"GenX.write_multi_stage_capacities_charge","text":"write_multi_stage_capacities_charge(outpath::String, settings_d::Dict)\n\nThis function writes the file capacities_charge_multi_stage.csv to the Results directory. This file contains starting resource charge capacities from the first model stage and end resource charge capacities for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_capacities_energy","page":"Outputs Functions","title":"GenX.write_multi_stage_capacities_energy","text":"write_multi_stage_capacities_energy(outpath::String, settings_d::Dict)\n\nThis function writes the file capacities_energy_multi_stage.csv to the Results directory. This file contains starting resource energy capacities from the first model stage and end resource energy capacities for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-maintenance-files","page":"Outputs Functions","title":"Write maintenance files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_maintenance.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_maintenance-Tuple{AbstractString, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_maintenance","text":"write_maintenance(path::AbstractString, inputs::Dict, EP::Model)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-DCOPF-files","page":"Outputs Functions","title":"Write DCOPF files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_angles","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_angles","page":"Outputs Functions","title":"GenX.write_angles","text":"write_angles(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting the bus angles for each model zone and time step if the DC_OPF flag is activated\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Settings-files","page":"Outputs Functions","title":"Write Settings files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_settings.jl\"]","category":"page"},{"location":"Getting_Started/examples_casestudies/#Running-GenX","page":"Running GenX","title":"Running GenX","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"This section describes how to run GenX with the examples provided in the repository and with user-defined cases. To have a deeper understanding of how to structure the input files and the settings, please refer to the User Guide.","category":"page"},{"location":"Getting_Started/examples_casestudies/#Example-cases","page":"Running GenX","title":"Example cases","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"GenX repository contains several examples to get you started with GenX. These examples are located in the example_systems folder of the repository and are designed to be easy to run and to demonstrate the main features of GenX. ","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The available examples are:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"1_three_zones\n2_three_zones_w_electrolyzer\n3_three_zone_w_co2_capture\n4_three_zones_w_policies_slack\n5_three_zones_w_piecewise_fuel\n6_three_zones_w_multistage\n7_three_zones_w_colocated_VRE_storage\nIEEE_9_bus_DC_OPF","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"note: Note\nThe following instructions assume that you have already installed GenX and its dependencies. If you haven't, please follow the instructions in the Installation Guide.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"To run an example, follow these steps:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"Open a terminal and run Julia with an environment containing GenX;\nRun the Run.jl file located in the example folder.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"For example, to run the 1_three_zones example, you can use the following commands:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"$ julia\njulia> \n(@v1.9) pkg> activate /path/to/env\njulia> using GenX\njulia> include(\"/path/to/GenX/example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"where /path/to/env is the path to the environment containing GenX and /path/to/GenX is the path to the GenX repository containing the examples.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The Run.jl file will read the .csv input files which define the system, the resources, and the policies, will solve the model, and finally will write the results in a results folder located in the same directory as Run.jl.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"tip: Tip\nYou could also run the example from the terminal using the following command:$ julia --project=/path/to/env /path/to/GenX/example_systems/1_three_zones/Run.jl`This is equivalent to open a Julia REPL and call the Run.jl file using the include function. The first option is recommended if you want to run GenX multiple times with different settings because it avoids the overhead of recompiling the code every time you run it.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"note: Note\nThe default solver for GenX is HiGHS.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"For more information on what happens when you run a GenX case, see the Running GenX section.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"note: Note\nThe first seven examples are based on a one-year example with hourly resolution, containing zones representing Massachusetts, Connecticut, and Maine. The ten represented resources include natural gas, solar PV, wind, and lithium-ion battery storage.","category":"page"},{"location":"Getting_Started/examples_casestudies/#Running-GenX-with-user-defined-cases","page":"Running GenX","title":"Running GenX with user-defined cases","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"To run GenX with a user-defined case, you need to create a folder MyCase with the following structure:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"MyCase\n├── settings/\n├── system/\n├── policies/\n├── resources/\n├── README.md\n└── Run.jl","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"where the settings folder contains the configuration files for the model and the solver, the system folder contains the .csv input files related to the system under study, the resource folder contains the .csv input files with the list of generators to include in the model, and the policies folder contains the .csv input files which define the policies to be included in the model. For instance, one case could have the following structure:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"MyCase\n│ \n├── settings\n│ ├── genx_settings.yml # GenX settings\n│ ├── [solver_name]_settings.yml # Solver settings\n│ ├── multi_stage_settings.yml # Multi-stage settings\n│ └── time_domain_reduction.yml # Time-domain clustering settings\n│ \n├── system\n│ ├── Demand_data.csv\n│ ├── Fuel_data.csv\n│ ├── Generators_variability.csv\n│ └── Network.csv\n│ \n├── policies\n│ ├── CO2_cap.csv\n│ ├── Minimum_capacity_requirement.csv\n│ └── Energy_share_requirement.csv\n│ \n├── resources\n│ ├── Thermal.csv\n│ ├── Storage.csv\n│ ├── Vre.csv\n│ ├── Hydro.csv\n│ └── policy_assignments\n| ├── Resource_minimum_capacity_requirement.csv\n│ └── Resource_energy_share_requirement.csv\n│\n└── Run.jl","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"In this example, MyCase will define a case with Themal, Storage, Vre, and Hydro resources, the system folder will provide the data for the demand, fuel, generators' variability, and network, the policies folder will include a CO2 cap, a minimum capacity requirement, and an energy share requirement, and the settings folder will contain the configuration files for the model. ","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The Run.jl file should contain the following code:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"using GenX\n\nrun_genx_case!(dirname(@__FILE__))","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"which will run the case using the default solver. To use a different solver, you can pass the Optimizer object as an argument to run_genx_case! function. For example, to use Gurobi as the solver, you can use the following code:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"using GenX\nusing Gurobi\n\nrun_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"To run the case, open a terminal and run the following command:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"$ julia --project=\"/path/to/env\"\njulia> include(\"/path/to/MyCase/Run.jl\")","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"where /path/to/env is the path to the environment with GenX installed, and /path/to/MyCase is the path to the folder of the MyCase case. Alternatively, you can run the case directly from the terminal using the following command:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"$ julia --project=\"/path/to/env\" /path/to/MyCase/Run.jl","category":"page"},{"location":"Getting_Started/examples_casestudies/#What-happens-when-you-run-a-case","page":"Running GenX","title":"What happens when you run a case","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"Added in 0.3.4","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The entry point for running a GenX case is the run_genx_case!(\"path/to/case\") function, where path/to/case is the path to the case directory that contains the .csv files with the inputs for GenX and the settings folder with the configuration files.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The following are the main steps performed in this function:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"Establish path to environment setup files and GenX source files.\nRead in model settings genx_settings.yml from the example directory.\nConfigure solver settings.\nLoad the model inputs from the example directory and perform time-domain clustering if required.\nGenerate a GenX model instance.\nSolve the model.\nWrite the output files to a specified directory.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"After the script runs to completion, results will be written to a folder called results, located in the current working directory.","category":"page"},{"location":"installation/#Installation-Guide","page":"Installation Guide","title":"Installation Guide","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"This guide will walk you through the steps to install Julia, the GenX package, and the required dependencies to run GenX.","category":"page"},{"location":"installation/#Installing-Julia","page":"Installation Guide","title":"Installing Julia","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"GenX currently exists in version 0.4.0 and runs only on Julia v1.6.x, 1.7.x, 1.8.x, and 1.9.x, where x>=0 and a minimum version of JuMP v1.1.1. To install Julia, please follow the instructions on the Julia website.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"note: Note\nWe recommend the users to stick to a particular version of Julia to run GenX. If however, the users decide to switch between versions, it's very important to delete the old Manifest.toml file and do a fresh build of GenX.","category":"page"},{"location":"installation/#Downloading-GenX-and-installing-dependencies","page":"Installation Guide","title":"Downloading GenX and installing dependencies","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"After installing Julia, you can download GenX by either cloning the repository or downloading the zip file from the GenX GitHub page. For this tutorial it will be assumed to be within your home directory: /home/youruser/GenX. Once you have downloaded GenX, you can install the dependencies by following the steps below:","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"1. Start a terminal and navigate into the GenX folder.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"2. Type julia --project=. to start an instance of the julia kernel with the project set to the current folder. The flag --project=. indicates that Julia will activate the project environment using the Project.toml present in the current folder, .. If running on Windows, the location of Julia can also be specified as e.g., C:\\julia-1.6.0\\bin\\julia.exe --project=..","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"tip: Tip\nThe file Project.toml in the parent directory lists all of the dependencies and their versions needed to run GenX. You can see all of the packages installed in your Julia environment and their version numbers by running pkg> status or pkg> st on the package manager command line in the Jula REPL (for more information on the Julia package manager, read the documentation for the Pkg.jl or for the Julia standard library).","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"tip: Tip\njulia --project is a shortcut for julia --project=.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"3. Type ] to bring up the package system (GenX) pkg > prompt. This indicates that the GenX project was detected. ","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"warning: Warning\nIf you see (@v1.6) pkg> as the prompt, then the project was not successfully set.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"4. Type instantiate from the (GenX) pkg prompt.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"note: Note for Windows users\nOn Windows there is an issue with the prepopulated MUMPS_seq_jll v5.5.1 that prevents compilation of the solvers. To avoid this issue type add MUMPS_seq_jll@5.4.1 after running instantiate.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"5. Type st to check that the dependecies have been installed. If there is no error, it has been successful.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"tip: Tip\nType the back key to come back to the julia> prompt from the package manager.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"The above steps are shown in Figure 1 and Figure 2.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"(Image: Creating the Julia environment and installing dependencies: Steps 2-4) Figure 1. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"(Image: Creating the Julia environment and installing dependencies: Step 5) Figure 2. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder: Step 5","category":"page"},{"location":"installation/#Installing-solvers","page":"Installation Guide","title":"Installing solvers","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"GenX requires a solver to be installed to solve the optimization problem. By default, GenX uses one of the following open-source freely available solvers:","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"HiGHS for linear programming and MILP (default solver)\nClp for linear programming (LP) problems\nCbc for mixed integer linear programming (MILP) problems","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"We also provide the option to use one of these two commercial solvers: ","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"Gurobi\nCPLEX.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"note: Note on commercial solvers\nUsing Gurobi and CPLEX requires a valid license on the host machine.","category":"page"},{"location":"installation/#Notes-on-previous-versions-of-GenX","page":"Installation Guide","title":"Notes on previous versions of GenX","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"For those users who has previously cloned GenX, and has been running it successfully so far, and therefore might be unwilling to run it on the latest version of Julia: please look into the GitHub branch, old_version.","category":"page"},{"location":"Model_Reference/Resources/resource/#Resource-types-and-function-interfaces","page":"Resource types","title":"Resource types and function interfaces","text":"","category":"section"},{"location":"Model_Reference/Resources/resource/","page":"Resource types","title":"Resource types","text":"GenX.AbstractResource","category":"page"},{"location":"Model_Reference/Resources/resource/#GenX.AbstractResource","page":"Resource types","title":"GenX.AbstractResource","text":"An abstract type that should be subtyped for users creating GenX resources.\n\n\n\n\n\n","category":"type"},{"location":"Model_Reference/Resources/resource/","page":"Resource types","title":"Resource types","text":"Modules = [GenX]\nPages = [\"resources.jl\"]","category":"page"},{"location":"Model_Reference/Resources/resource/#GenX.default_zero","page":"Resource types","title":"GenX.default_zero","text":"const default_zero = 0\n\nDefault value for resource attributes.\n\n\n\n\n\n","category":"constant"},{"location":"Model_Reference/Resources/resource/#GenX.resource_types","page":"Resource types","title":"GenX.resource_types","text":"resource_types\n\nName of the type of resources available in the model.\n\nPossible values:\n\n:Thermal\n:Vre\n:Hydro\n:Storage\n:MustRun\n:FlexDemand\n:VreStorage\n:Electrolyzer\n\n\n\n\n\n","category":"constant"},{"location":"Model_Reference/Resources/resource/#Base.findall-Tuple{Function, Vector{var\"#s1937\"} where var\"#s1937\"<:GenX.AbstractResource}","page":"Resource types","title":"Base.findall","text":"findall(f::Function, rs::Vector{<:AbstractResource})\n\nFind all resources in the vector rs that satisfy the condition given by the function f. Return the resource id instead of the vector index.\n\nArguments\n\nf::Function: The condition function.\nrs::Vector{<:AbstractResource}: The vector of resources.\n\nReturns\n\nVector: The vector of resource ids.\n\nExamples\n\njulia> findall(r -> max_cap_mwh(r) != 0, gen.Storage)\n3-element Vector{Int64}:\n 48\n 49\n 50\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.get-Tuple{GenX.AbstractResource, Symbol, Any}","page":"Resource types","title":"Base.get","text":"Base.get(r::AbstractResource, sym::Symbol, default)\n\nRetrieves the value of a specific attribute from an AbstractResource object. If the attribute exists, its value is returned; otherwise, the default value is returned.\n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\ndefault: The default value to return if the attribute does not exist.\n\nReturns:\n\nThe value of the attribute if it exists in the parent object, default otherwise.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.getproperty-Tuple{GenX.AbstractResource, Symbol}","page":"Resource types","title":"Base.getproperty","text":"Base.getproperty(r::AbstractResource, sym::Symbol)\n\nAllows to access the attributes of an AbstractResource object using dot syntax. It checks if the attribute exists in the object and returns its value, otherwise it throws an ErrorException indicating that the attribute does not exist.\n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\n\nReturns:\n\nThe value of the attribute if it exists in the parent object.\n\nThrows:\n\nErrorException: If the attribute does not exist in the resource.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.getproperty-Tuple{Vector{var\"#s1937\"} where var\"#s1937\"<:GenX.AbstractResource, Symbol}","page":"Resource types","title":"Base.getproperty","text":"Base.getproperty(rs::Vector{<:AbstractResource}, sym::Symbol)\n\nAllows to access attributes of a vector of AbstractResource objects using dot syntax. If the sym is an element of the resource_types constant, it returns all resources of that type. Otherwise, it returns the value of the attribute for each resource in the vector.\n\nArguments:\n\nrs::Vector{<:AbstractResource}: The vector of AbstractResource objects.\nsym::Symbol: The symbol representing the attribute name or a type from resource_types.\n\nReturns:\n\nIf sym is an element of the resource_types constant, it returns a vector containing all resources of that type.\nIf sym is an attribute name, it returns a vector containing the value of the attribute for each resource.\n\nExamples\n\njulia> vre_gen = gen.Vre; # gen vector of resources\njulia> typeof(vre_gen)\nVector{Vre} (alias for Array{Vre, 1})\njulia> vre_gen.zone\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.haskey-Tuple{GenX.AbstractResource, Symbol}","page":"Resource types","title":"Base.haskey","text":"haskey(r::AbstractResource, sym::Symbol)\n\nCheck if an AbstractResource object has a specific attribute. It returns a boolean value indicating whether the attribute exists in the parent object.\n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\n\nReturns:\n\ntrue if the attribute exists in the parent object, false otherwise.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.pairs-Tuple{GenX.AbstractResource}","page":"Resource types","title":"Base.pairs","text":"pairs(r::AbstractResource)\n\nReturn an iterator of key-value pairs with the attributes of a given resource.\n\nArguments\n\nr::AbstractResource: The resource.\n\nReturns\n\nPairs: An iterator of key-value pairs over the attributes.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.setindex!-Tuple{Vector{var\"#s1935\"} where var\"#s1935\"<:GenX.AbstractResource, Vector{T} where T, Symbol}","page":"Resource types","title":"Base.setindex!","text":"Base.setindex!(rs::Vector{<:AbstractResource}, value::Vector, sym::Symbol)\n\nDefine dot syntax for setting the attributes specified by sym to the corresponding values in value for a vector of resources.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nvalue::Vector: The vector of values to set for the attribute.\nsym::Symbol: The symbol representing the attribute to set.\n\nReturns\n\nrs::Vector{<:AbstractResource}: The updated vector of resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.setproperty!-Tuple{GenX.AbstractResource, Symbol, Any}","page":"Resource types","title":"Base.setproperty!","text":"setproperty!(r::AbstractResource, sym::Symbol, value)\n\nAllows to set the attribute sym of an AbstractResource object using dot syntax. \n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\nvalue: The value to set for the attribute.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.setproperty!-Tuple{Vector{var\"#s1935\"} where var\"#s1935\"<:GenX.AbstractResource, Symbol, Vector{T} where T}","page":"Resource types","title":"Base.setproperty!","text":"Base.setproperty!(rs::Vector{<:AbstractResource}, sym::Symbol, value::Vector)\n\nSet the attributes specified by sym to the corresponding values in value for a vector of resources.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nsym::Symbol: The symbol representing the attribute to set.\nvalue::Vector: The vector of values to set for the attribute.\n\nReturns\n\nrs::Vector{<:AbstractResource}: The updated vector of resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.show-Tuple{IO, GenX.AbstractResource}","page":"Resource types","title":"Base.show","text":"show(io::IO, r::AbstractResource)\n\nPrint the attributes of the given resource.\n\nArguments\n\nio::IO: The IO stream to print to.\nr::AbstractResource: The resource.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.attributes-Tuple{GenX.AbstractResource}","page":"Resource types","title":"GenX.attributes","text":"attributes(r::AbstractResource)\n\nReturns a tuple of the attribute names of the given resource.\n\nArguments\n\nr::AbstractResource: The resource.\n\nReturns\n\nTuple: A tuple with symbols representing the attribute names.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.electrolyzer-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.electrolyzer","text":"electrolyzer(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all electrolyzer resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.flex_demand-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.flex_demand","text":"flex_demand(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all flexible demand resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.has_all_options_contributing-Union{Tuple{T}, Tuple{GenX.AbstractResource, Vector{T}}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.has_all_options_contributing","text":"has_all_options_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource\n\nCheck if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res contribute to min retirement.\n\nArguments\n\nretrofit_res::AbstractResource: The retrofit resource.\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nBool: True if all retrofit options contribute to min retirement, otherwise false.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.has_all_options_not_contributing-Union{Tuple{T}, Tuple{GenX.AbstractResource, Vector{T}}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.has_all_options_not_contributing","text":"has_all_options_not_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource\n\nCheck if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res do not contribute to min retirement.\n\nArguments\n\nretrofit_res::AbstractResource: The retrofit resource.\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nBool: True if all retrofit options do not contribute to min retirement, otherwise false.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.hydro-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.hydro","text":"hydro(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all hydro resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with-Union{Tuple{T}, Tuple{Vector{T}, Function}, Tuple{Vector{T}, Function, Any}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with","text":"ids_with(rs::Vector{T}, f::Function, default=default_zero) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by f is not equal to default.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The getter of the attribute.\ndefault: The default value of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with attribute not equal to default.\n\nExamples\n\njulia> ids_with(gen.Thermal, existing_cap_mw)\n4-element Vector{Int64}:\n 21\n 22\n 23\n 24\njulia> existing_cap_mw(gen[21])\n7.0773\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with-Union{Tuple{T}, Tuple{Vector{T}, Symbol}, Tuple{Vector{T}, Symbol, Any}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with","text":"ids_with(rs::Vector{T}, name::Symbol, default=default_zero) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by name is not equal to the default value of the attribute.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the attribute.\ndefault: The default value of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with attribute not equal to default.\n\nExamples\n\njulia> ids_with(gen.Thermal, :existing_cap_mw)\n4-element Vector{Int64}:\n 21\n 22\n 23\n 24\njulia> existing_cap_mw(gen[21])\n7.0773\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_all_options_contributing-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_all_options_contributing","text":"ids_with_all_options_contributing(rs::Vector{T}) where T <: AbstractResource\n\nFind the resource ids of the retrofit units in the vector rs where all retrofit options contribute to min retirement.\n\nArguments\n\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nVector{Int64}: The vector of resource ids.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_all_options_not_contributing-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_all_options_not_contributing","text":"ids_with_all_options_not_contributing(rs::Vector{T}) where T <: AbstractResource\n\nFind the resource ids of the retrofit units in the vector rs where all retrofit options do not contribute to min retirement.\n\nArguments\n\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nVector{Int64}: The vector of resource ids.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_nonneg-Union{Tuple{T}, Tuple{Vector{T}, Function}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_nonneg","text":"ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by f is non-negative.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The getter of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with non-negative attribute.\n\nExamples\n\njulia> ids_with_nonneg(gen, max_cap_mw)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_nonneg-Union{Tuple{T}, Tuple{Vector{T}, Symbol}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_nonneg","text":"ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by name is non-negative.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with non-negative attribute.\n\nExamples\n\njulia> ids_with_nonneg(gen, max_cap_mw)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_policy-Union{Tuple{T}, Tuple{Vector{T}, Function}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_policy","text":"ids_with_policy(rs::Vector{T}, f::Function; tag::Int64) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the policy specified by f with tag equal to tag is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The policy getter function.\ntag::Int64: The tag of the policy.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with a positive value for policy f and tag tag.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_policy-Union{Tuple{T}, Tuple{Vector{T}, Symbol}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_policy","text":"idswithpolicy(rs::Vector{T}, name::Symbol; tag::Int64) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the policy specified by name with tag equal to tag is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the policy.\ntag::Int64: The tag of the policy.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with a positive value for policy name and tag tag.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_positive-Union{Tuple{T}, Tuple{Vector{T}, Function}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_positive","text":"ids_with_positive(rs::Vector{T}, f::Function) where T <: AbstractResource\n\nFunction for finding indices of resources in a vector rs where the attribute specified by f is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The getter of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with positive attribute.\n\nExamples\n\njulia> ids_with_positive(gen, max_cap_mw)\n3-element Vector{Int64}:\n 3 \n 4\n 5\njulia> max_cap_mw(gen[3])\n4.888236\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_positive-Union{Tuple{T}, Tuple{Vector{T}, Symbol}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_positive","text":"ids_with_positive(rs::Vector{T}, name::Symbol) where T <: AbstractResource\n\nFunction for finding indices of resources in a vector rs where the attribute specified by name is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the attribute.\n\nReturns\n\nVector{Int64}: The vector of resource ids with positive attribute.\n\nExamples\n\njulia> ids_with_positive(gen, :max_cap_mw)\n3-element Vector{Int64}:\n 3 \n 4\n 5\njulia> max_cap_mw(gen[3])\n4.888236\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.must_run-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.must_run","text":"must_run(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all must-run resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.resource_by_name-Tuple{Vector{var\"#s1937\"} where var\"#s1937\"<:GenX.AbstractResource, AbstractString}","page":"Resource types","title":"GenX.resource_by_name","text":"resource_by_name(rs::Vector{<:AbstractResource}, name::AbstractString)\n\nFind the resource with name in the vector rs.\n\nArguments\n\nrs: A vector of resources.\nname: The name of the resource.\n\nReturns\n\nAbstractResource: The resource with the name name.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.resources_in_retrofit_cluster_by_rid-Tuple{Vector{var\"#s1937\"} where var\"#s1937\"<:GenX.AbstractResource, String}","page":"Resource types","title":"GenX.resources_in_retrofit_cluster_by_rid","text":"resources_in_retrofit_cluster_by_rid(rs::Vector{<:AbstractResource}, cluster_id::String)\n\nFind RID's of resources with retrofit cluster id `clusterid`.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\ncluster_id::String: The retrofit cluster id.\n\nReturns\n\nVector{Int64}: The vector of resource ids in the retrofit cluster.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.resources_in_zone_by_rid-Tuple{Vector{var\"#s1937\"} where var\"#s1937\"<:GenX.AbstractResource, Int64}","page":"Resource types","title":"GenX.resources_in_zone_by_rid","text":"resources_in_zone_by_rid(rs::Vector{<:AbstractResource}, zone::Int)\n\nFind R_ID's of resources in a zone.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.solar-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.solar","text":"solar(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located solar resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage","text":"storage(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all storage resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_ac_charge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_ac_charge","text":"storage_ac_charge(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located storage resources in the vector rs that charge AC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_ac_discharge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_ac_discharge","text":"storage_ac_discharge(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located storage resources in the vector rs that discharge AC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_dc_charge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_dc_charge","text":"storage_dc_charge(rs::Vector{T}) where T <: AbstractResource\nReturns the indices of all co-located storage resources in the vector `rs` that charge DC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_dc_discharge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_dc_discharge","text":"storage_dc_discharge(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located storage resources in the vector rs that discharge DC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.thermal-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.thermal","text":"thermal(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all thermal resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.validate_boolean_attribute-Tuple{GenX.AbstractResource, Symbol}","page":"Resource types","title":"GenX.validate_boolean_attribute","text":"validate_boolean_attribute(r::AbstractResource, attr::Symbol)\n\nValidate that the attribute attr in the resource r is boolean {0, 1}.\n\nArguments\n\nr::AbstractResource: The resource.\nattr::Symbol: The name of the attribute.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.vre-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.vre","text":"vre(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all Vre resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.vre_stor-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.vre_stor","text":"vre_stor(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all VRE_STOR resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.wind-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.wind","text":"wind(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located wind resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.@interface","page":"Resource types","title":"GenX.@interface","text":"interface(name, default=default_zero, type=AbstractResource)\n\nDefine a function interface for accessing the attribute specified by name in a resource of type type.\n\nArguments\n\nname: The name of the attribute.\ndefault: The default value to return if the attribute is not found.\ntype: The type of the resource.\n\nReturns\n\nFunction: The generated function.\n\nExamples\n\njulia> @interface max_cap_mw 0 Vre\njulia> max_cap_mw(gen.Vre[3])\n4.888236\njulia> max_cap_mw.(gen.Vre) # vectorized\n5-element Vector{Float64}:\n 0.0\n 0.0\n 4.888236\n 20.835569\n 9.848441999999999\n\n\n\n\n\n","category":"macro"},{"location":"Model_Reference/Resources/hydro_inter_period_linkage/#Reservoir-Hydro","page":"Long Duration Hydro","title":"Reservoir Hydro","text":"","category":"section"},{"location":"Model_Reference/Resources/hydro_inter_period_linkage/","page":"Long Duration Hydro","title":"Long Duration Hydro","text":"Modules = [GenX]\nPages = [\"hydro_inter_period_linkage.jl\"]","category":"page"},{"location":"Model_Reference/Resources/hydro_inter_period_linkage/#GenX.hydro_inter_period_linkage!-Tuple{JuMP.Model, Dict}","page":"Long Duration Hydro","title":"GenX.hydro_inter_period_linkage!","text":"hydro_inter_period_linkage!(EP::Model, inputs::Dict)\n\nThis function creates variables and constraints enabling modeling of long duration storage resources when modeling representative time periods.\n\nStorage inventory balance at beginning of each representative period The constraints in this section are used to approximate the behavior of long-duration energy storage technologies when approximating annual grid operations by modeling operations over representative periods. Previously, the state of charge balance for storage (as defined in storage_all()) assumed that state of charge at the beginning and end of each representative period has to be the same. In other words, the amount of energy built up or consumed by storage technology o in zone z over the representative period m, Delta Q_ozm = 0. This assumption implicitly excludes the possibility of transferring energy from one representative period to the other which could be cost-optimal when the capital cost of energy storage capacity is relatively small. To model long-duration energy storage using representative periods, we replace the state of charge equation, such that the first term on the right hand side accounts for change in storage inventory associated with representative period m (Delta Q_ozm), which could be positive (net accumulation) or negative (net reduction).\n\nbeginaligned\n Gamma_oz(m-1)times tau^period+1 =left(1-eta_oz^lossright)times left(Gamma_ozmtimes tau^period -Delta Q_ozmright) - \n frac1eta_oz^dischargeTheta_oz(m-1)times tau^period+1 + eta_oz^chargePi_oz(m-1)times tau^period+1 quad forall o in mathcalO^LDES z in mathcalZ m in mathcalM\nendaligned\n\nBy definition mathcalT^start=left(m-1right) times tau^period+1 m in mathcalM, which implies that this constraint is defined for all values of t in T^start.\n\nStorage inventory change input periods We need additional variables and constraints to approximate energy exchange between representative periods, while accounting for their chronological occurence in the original input time series data and the possibility that two representative periods may not be adjacent to each other (see Figure below). To implement this, we introduce a new variable Q_oz n that models inventory of storage technology o in O in zone z in each input period n in mathcalN. Additionally we define a function mapping, f n rightarrow m, that uniquely maps each input period n to its corresponding representative period m. This mapping is available as an output of the process used to identify representative periods (E.g. k-means clustering Mallapragada et al., 2018). (Image: Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations) Figure. Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations The following two equations define the storage inventory at the beginning of each input period n+1 as the sum of storage inventory at begining of previous input period n plus change in storage inventory for that period. The latter is approximated by the change in storage inventory in the corresponding representative period, identified per the mapping f(n). The second constraint relates the storage level of the last input period, N, with the storage level at the beginning of the first input period. Finally, if the input period is also a representative period, then a third constraint enforces that initial storage level estimated by the intra-period storage balance constraint should equal the initial storage level estimated from the inter-period storage balance constraints. Note that N refers to the last modeled period.\n\nbeginaligned\n Q_ozn+1 = Q_ozn + Delta Q_ozf(n)\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalNsetminusN\nendaligned\n\nbeginaligned\n Q_oz1 = Q_ozN + Delta Q_ozf(N)\nquad forall o in mathcalO^LDES z in mathcalZ n = N\nendaligned\n\nbeginaligned\n Q_ozn =Gamma_ozf(n)times tau^period - Delta Q_ozm\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalN^rep\nendaligned\n\nFinally, the next constraint enforces that the initial storage level for each input period n must be less than the installed energy capacity limit. This constraint ensures that installed energy storage capacity is consistent with the state of charge during both the operational time periods t during each sample period m as well as at the start of each chronologically ordered input period n in the full annual time series.\n\nbeginaligned\n Q_ozn leq Delta^total energy_oz\nquad forall n in mathcalN o in mathcalO^LDES\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/investment_energy/#Investment-Energy","page":"Investment Energy","title":"Investment Energy","text":"","category":"section"},{"location":"Model_Reference/Resources/investment_energy/","page":"Investment Energy","title":"Investment Energy","text":"Modules = [GenX]\nPages = [\"investment_energy.jl\"]","category":"page"},{"location":"Model_Reference/Resources/investment_energy/#GenX.investment_energy!-Tuple{JuMP.Model, Dict, Dict}","page":"Investment Energy","title":"GenX.investment_energy!","text":"investment_energy!(EP::Model, inputs::Dict)\n\nThis function defines the expressions and constraints keeping track of total available storage charge capacity across all resources as well as constraints on capacity retirements. The function also adds investment and fixed O\\&M related costs related to charge capacity to the objective function.\n\nThe total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity.\n\nbeginaligned\n Delta^totalenergy_yz =(overlineDelta^energy_yz+Omega^energy_yz-Delta^energy_yz) forall y in mathcalO z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity.\n\nbeginaligned\nDelta^energy_yz leq overlineDelta^energy_yz\n\t\thspace4 cm forall y in mathcalO z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^energy and underlineOmega_yz^energy is defined, then we impose constraints on minimum and maximum power capacity.\n\nbeginaligned\n Delta^totalenergy_yz leq overlineOmega^energy_yz\n\thspace4 cm forall y in mathcalO z in mathcalZ \n Delta^totalenergy_yz geq underlineOmega^energy_yz\n\thspace4 cm forall y in mathcalO z in mathcalZ\nendaligned\n\nIn addition, this function adds investment and fixed O\\&M related costs related to charge capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalO sum_z in mathcalZ\n\tleft( (pi^INVESTenergy_yz times Omega^energy_yz)\n\t+ (pi^FOMenergy_yz times Delta^totalenergy_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"User_Guide/slack_variables_overview/#Policy-Slack-Variables","page":"Slack Variables for Policies","title":"Policy Slack Variables","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Added in 0.3.5","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Rather than modeling policy requirements as inflexible constraints, it may be advantageous to instead allow these requirements to be violated at some predetermined cost. This is accomplished via 'slack variables,' which can be used by the model to meet a policy constraint if it cannot be met cost-effectively by normal means. Once the incremental shadow price of meeting a policy constraint rises above a cost threshold set by the user, the model will rely on the slack variable to fill any remaining gap. ","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Using slack variables rather than hard constraints may be useful for GenX users who wish to avoid unexpected infeasibilities resulting from policy requirements that cannot be met. Using slack variables with very high cost thresholds, users can quickly identify specific policy constraints that are effectively infeasible without causing errors. ","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables with lower assigned costs can also be used to model policies with built-in cost thresholds, for example a CO2 Cap with a maximum allowable carbon price of $200/ton. They can be activated for each individual policy type available in GenX, including: Capacity Reserve Margins, Energy Share Requirements, CO2 Caps, Minimum Capacity Requirements, and Maximum Capacity Requirements. ","category":"page"},{"location":"User_Guide/slack_variables_overview/#Running-cases-with-slack-variables","page":"Slack Variables for Policies","title":"Running cases with slack variables","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables are turned off by default in GenX, but can be automatically activated for each policy type by providing the relevant inputs. Slack variables will only be activated when the relevant policy type is itself activated in GenX_settings.yml. For some policy types, slack variables are activated by providing a new input file, while for others they are activated by modifying an existing file. Instructions for each policy type are listed below:","category":"page"},{"location":"User_Guide/slack_variables_overview/#Capacity-Reserve-Margin","page":"Slack Variables for Policies","title":"Capacity Reserve Margin","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Capacity Reserve Margin constraints are created when GenX detects the presence of the file Capacity_reserve_margin_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CRMConstraint' naming the individual Capacity Reserve Margin constraints in the same order in which they are listed in the first row of `Capacityreserve_margin.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /MW.","category":"page"},{"location":"User_Guide/slack_variables_overview/#CO2-Cap","page":"Slack Variables for Policies","title":"CO2 Cap","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for CO2 Cap constraints are created when GenX detects the presence of the file CO2_cap_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CO2CapConstraint' naming the individual CO2 Cap constraints in the same order in which they are listed in the first row of CO2_Cap.csv, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /ton. The CO2 Cap slack variable itself is always in units of tons of CO2, even if the CO2 Cap is a rate-based cap.","category":"page"},{"location":"User_Guide/slack_variables_overview/#Energy-Share-Requirement","page":"Slack Variables for Policies","title":"Energy Share Requirement","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Energy Share Requirement constraints are created when GenX detects the presence of the file Energy_share_requirement_slack.csv in the Inputs folder. This file should contain two columns: one titled 'ESRConstraint' naming the individual Energy Share Requirement constraints in the same order in which they are listed in the first row of `Energyshare_requirement.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are $/MWh.","category":"page"},{"location":"User_Guide/slack_variables_overview/#Minimum-Capacity-Requirement","page":"Slack Variables for Policies","title":"Minimum Capacity Requirement","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Minimum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Minimum_capacity_requirement.csv. This column contains the price thresholds for each Minimum Capacity Requirement constraint, in units of $/MW. ","category":"page"},{"location":"User_Guide/slack_variables_overview/#Maximum-Capacity-Requirement","page":"Slack Variables for Policies","title":"Maximum Capacity Requirement","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Maximum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Maximum_capacity_requirement.csv. This column contains the price thresholds for each Maximum Capacity Requirement constraint, in units of $/MW. ","category":"page"},{"location":"User_Guide/slack_variables_overview/#Slack-Variables-Results-Files","page":"Slack Variables for Policies","title":"Slack Variables Results Files","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"By default, a policy type's result files include the shadow prices for each policy constraint. When slack variables are activated, outputs also include the final values of the slack variables (i.e. the amount by which the policy constraint was violated), and the total costs associated with those slack variables. These files are named using the convention X_prices_and_penalties.csv, where X is the name of the relevant policy type.","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"GenX will also print the total cost associated with each activated slack variable type in the file costs.csv.","category":"page"},{"location":"User_Guide/slack_variables_overview/#Slack-Variables-Example","page":"Slack Variables for Policies","title":"Slack Variables Example","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"The folder Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example contains examples of the input files needed to activate slack variables for each of the policy types in GenX. Running this example with a given set of policy constraints activated will generate the relevant slack variables and print their outputs.","category":"page"},{"location":"User_Guide/generate_alternatives/#Running-Modeling-to-Generate-Alternatives-with-GenX","page":"MGA package","title":"Running Modeling to Generate Alternatives with GenX","text":"","category":"section"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"GenX includes a modeling to generate alternatives (MGA) package that can be used to automatically enumerate a diverse set of near cost-optimal solutions to electricity system planning problems. To use the MGA algorithm, user will need to perform the following tasks:","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"Add a Resource_Type column in all the resource .csv files denoting the type of each technology.\nAdd a MGA column in all the resource .csv files denoting the availability of the technology.\nSet the ModelingToGenerateAlternatives flag in the GenX_Settings.yml file to 1.\nSet the ModelingtoGenerateAlternativeSlack flag in the GenX_Settings.yml file to the desirable level of slack.\nCreate a Rand_mga_objective_coefficients.csv file to provide random objective function coefficients for each MGA iteration.","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"For each iteration, number of rows in the Rand_mga_objective_coefficients.csv file represents the number of distinct technology types while number of columns represent the number of model zones.","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"Solve the model using Run.jl file.","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"Results from the MGA algorithm would be saved in MGAmax and MGAmin folders in the Example_Systems/ folder.","category":"page"},{"location":"User_Guide/TDR_input/#Time-domain-reduction","page":"Time-domain Reduction Inputs","title":"Time-domain reduction","text":"","category":"section"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"Modeling grid operations for each hour of the year can be computationally expensive for models with many zones and resources. Rather than modeling and optimizing power grid operations at a high temporal resolution (e.g., hourly, over a full year) while evaluating new capacity investments, which can be computationally expensive for large-scale studies with several resources, it may be useful to consider a reduced temporal resolution to model annual grid operations. Time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. Such a time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. GenX allows the option of performing time-domain reduction on the user supplied time-series input data to produce a representative time series at the desired level of temporal resolution. The time-domain reduction method provided allows the user to automate these features while specifying the various parameters of the time-domain reduction 'clustering' algorithm to be used in formulating the resulting optimization model. The below table summarizes the list of parameters to be specified by the user to perform the time domain reduction implemented in GenX. These parameters are passed to GenX via the YAML file time_domain_reduction_settings.yml.","category":"page"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"It's also possible for GenX perform clustering separately from the optimization task. Check out the Running a case with Time Domain Reduction section for more information. ","category":"page"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"Structure of the time_domain_reduction.yml file","category":"page"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"Key Description\nTimesteps_per_period The number of timesteps (e.g., hours) in each representative period (i.e. 168 for weeks, 24 for days, 72 for three-day periods, etc).\nUseExtremePeriods 1 = Include outliers (by performance or demand/resource extreme) as their own representative extreme periods. This setting automatically includes periods based on criteria outlined in the dictionary ExtremePeriods. Extreme periods can be selected based on following criteria applied to demand profiles or solar and wind capacity factors profiles, at either the zonal or system level. A) absolute (timestep with min/max value) statistic (minimum, maximum) and B) integral (period with min/max summed value) statistic (minimum, maximum). For example, the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select Demand, System, Absolute, and Max.\n 0 = Do not include extreme periods.\nExtremePeriods If UseExtremePeriods = 1, use this dictionary to select which types of extreme periods to use. Select by profile type (Demand, PV, or Wind), geography (Zone or System), grouping by timestep or by period (Absolute or Integral), and statistic (Maximum or Minimum).\nClusterMethod Either kmeans or kmedoids, the method used to cluster periods and determine each time step's representative period.\nScalingMethod Either N or S, the decision to normalize ([0,1]) or standardize (mean 0, variance 1) the input data prior to clustering.\nMinPeriods The minimum number of representative periods used to represent the input data. If using UseExtremePeriods, this must be greater or equal to the number of selected extreme periods. If IterativelyAddPeriods is off, this will be the total number of representative periods.\nMaxPeriods The maximum number of representative periods - both clustered and extreme - that may be used to represent the input data.\nIterativelyAddPeriods 1 = Add representative periods until the error threshold between input data and represented data is met or the maximum number of representative periods is reached.\n 0 = Use only the minimum number of representative periods. This minimum value includes the selected extreme periods if UseExtremePeriods is on.\nThreshold Iterative period addition will end if the period farthest from its representative period (as measured using Euclidean distance) is within this percentage of the total possible error (for normalization) or 95% of the total possible error (± 2 σ for standardization). E.g., for a threshold of 0.01, each period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the maximum is reached).\nIterateMethod Either ‘cluster' (Default) or ‘extreme', whether to increment the number of clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.\nnReps Default = 200, the number of kmeans/kmedoids repetitions at the same setting.\nDemandWeight Default = 1, a multiplier on demand columns to optionally prioritize better fits for demand profiles over resource capacity factor or fuel price profiles.\nWeightTotal Default = 8760, the sum to which the relative weights of representative periods will be scaled.\nClusterFuelPrices Either 1 or 0, whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data.csv in the TimeDomainReductionFolder with reshaped fuel prices based on the number and size of the representative periods but will not use the fuel price time series for selection of representative periods.","category":"page"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#Dual-Dynamic-Programming-Algorithm","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"Dual Dynamic Programming Algorithm","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"Model multi stage: Dual Dynamic Programming Algorithm","text":"Modules = [GenX]\nPages = [\"dual_dynamic_programming.jl\"]","category":"page"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.add_cut-Tuple{JuMP.Model, JuMP.Model, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.add_cut","text":"add_cut(EP_cur::Model, EP_next::Model, start_cap_d::Dict, cap_track_d::Dict)\n\ninputs:\n\nEP_cur - JuMP model from the current model stage p.\nEP_next - JuMP model from the next model stage p+1..\nstart_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\ncap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\n\nreturns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.configure_ddp_dicts-Tuple{Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.configure_ddp_dicts","text":"configure_ddp_dicts(setup::Dict, inputs::Dict)\n\nThis function instantiates Dictionary objects containing the names of linking expressions, constraints, and variables used in multi-stage modeling.\n\ninputs:\n\nsetup - Dictionary object containing GenX settings and key parameters.\ninputs – Dictionary of inputs for each model period, generated by the load_inputs() method.\n\nreturns:\n\nstart_cap_d – Dictionary which contains linking expression names as keys and linking constraint names as values, used for setting the end capacity in stage p to the starting capacity in stage p+1.\ncap_track_d – Dictionary which contains linking variable names as keys and linking constraint names as values, used for enforcing endogenous retirements.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.fix_capacity_tracking-Tuple{JuMP.Model, JuMP.Model, Dict, Int64}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.fix_capacity_tracking","text":"fix_capacity_tracking(EP_prev::Model, EP_cur::Model, cap_track_d::Dict, cur_stage::Int)\n\nThis function sets the right hand side values of the new and retired capacity tracking linking constraints in the current stage p to the realized values of the new and retired capacity tracking linking variables from the previous stage p-1 as part of the forward pass. where tracking linking variables are defined variables for tracking, linking and passing realized expansion and retirement of capacities of each stage to the next stage. Tracking linking variables are each defined in endogenous_retirement_discharge, endogenous_retirement_energy, and endogenous_retirement_charge functions. Three examples are \"vCAPTRACK\", \"vCAPTRACKCHARGE\", and \"\"vCAPTRACKENERGY\"\n\ninputs:\n\nEP_prev - JuMP model from the previous model stage p-1.\nEP_cur - JuMP model from the current model stage p.\ncap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\ncur_period – Int representing the current model stage p.\n\nreturns: JuMP model with updated linking constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.fix_initial_investments-Tuple{JuMP.Model, JuMP.Model, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.fix_initial_investments","text":"fix_initial_investments(EP_prev::Model, EP_cur::Model, start_cap_d::Dict)\n\nThis function sets the right hand side values of the existing capacity linking constraints in the current stage p to the realized values of the total available end capacity linking variable expressions from the previous stage p-1 as part of the forward pass.\n\ninputs:\n\nEP_prev - JuMP model from the previous model stage p-1.\nEP_cur - JuMP model from the current model stage p.\nstart_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\n\nreturns: JuMP model with updated linking constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.generate_cut_component_inv-Tuple{JuMP.Model, JuMP.Model, Symbol, Symbol}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.generate_cut_component_inv","text":"generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)\n\nThis function generates Bender's cut expressions for linking capacity investment variable expression in the form:\n\nbeginaligned\n mu_next^top(hatx_cur - x_cur)\nendaligned\n\nwhere mu_next is a vector of dual values of the linking constraints defined by constr_name in EP_next, hatx_cur is a vector of realized values from the forward pass of the linking capacity investment variable expressions expr_name from EP_cur, and x_cur is a vector of unrealized linking capacity investment variable expressions from EP_cur. inputs:\n\ninputs:\n\nEP_cur - JuMP model from the current model stage p, solved in the forward pass.\nEP_next - JuMP model from the next model stage p+1, solved in the forward pass.\nexpr_name – Symbol representing the name of a JuMP expression array which contains linking capacity investment variables.\nconstr_name – Symbol representing the name of the array of linking JuMP constraints which contain the linking capacity investment variables.\n\nreturns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.generate_cut_component_track-Tuple{JuMP.Model, JuMP.Model, Symbol, Symbol}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.generate_cut_component_track","text":"generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)\n\nThis function generates Bender's cut expressions for total new or retired capacity tracking linking variables in the form:\n\nbeginaligned\n mu_next^top(hatx_cur - x_cur)\nendaligned\n\nwhere mu_next is a vector of dual values of the linking constraints defined by constr_name in EP_next, hatx_cur is a vector of realized values from the forward pass of the new or retired capacity tracking linking variables var_name from EP_cur, and x_cur is a vector of unrealized new or retired capacity tracking linking variables from EP_cur.\n\ninputs:\n\nEP_cur - JuMP model from the current model stage p.\nEP_next - JuMP model from the next model stage p+1.\nvar_name – Symbol representing the name of a JuMP variable array which contains total new or retired capacity tracking linking variables.\nconstr_name – Symbol representing the name of the array of linking JuMP constraints which contain total new or retired capacity tracking linking variables.\n\nreturns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.initialize_cost_to_go-Tuple{Dict, JuMP.Model, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.initialize_cost_to_go","text":"initialize_cost_to_go(settings_d::Dict, EP::Model)\n\nThis function scales the model objective function so that costs are consistent with multi-stage modeling and introduces a cost-to-go function variable to the objective function.\n\nThe updated objective function OBJ^* returned by this method takes the form:\n\nbeginaligned\n OBJ^* = DF * OPEXMULT * OBJ + alpha\nendaligned\n\nwhere OBJ is the original objective function. OBJ is scaled by two terms. The first is a discount factor (applied only in the non-myopic case), which discounts costs associated with the model stage p to year-0 dollars:\n\nbeginaligned\n DF = frac1(1+WACC)^L*(p-1)\nendaligned\n\nwhere WACC is the weighted average cost of capital, and L is the length of each stage in years (both set in multi_stage_settings.yml)\n\nThe second term is a discounted sum of annual operational expenses incurred each year of a multi-year model stage:\n\nbeginaligned\n OPEXMULT = sum^L_l=1frac1(1+WACC)^l-1\nendaligned\n\nNote that although the objective function contains investment costs, which occur only once and thus do not need to be scaled by OPEXMULT, these costs are multiplied by a factor of frac1WACC before being added to the objective function in investment_discharge_multi_stage(), investment_charge_multi_stage(), investment_energy_multi_stage(), and transmission_multi_stage(). Thus, this step scales these costs back to their correct value.\n\nThe cost-to-go function alpha represents an approximation of future costs given the investment and retirement decisions in the current stage. It is constructed through the addition of cuts to the cost-to-go function alpha during the backwards pass.\n\ninputs:\n\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\nEP – JuMP model.\n\nreturns: JuMP model with updated objective function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.run_ddp-Tuple{Dict, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.run_ddp","text":"run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)\n\nThis function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.\n\ninputs:\n\nmodels_d – Dictionary which contains a JuMP model for each model period.\nsetup - Dictionary object containing GenX settings and key parameters.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.\n\nreturns:\n\nmodels_d – Dictionary which contains a JuMP model for each model stage, modified by this method.\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.write_multi_stage_outputs-Tuple{Dict, String, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.write_multi_stage_outputs","text":"write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)\n\nThis function calls various methods which write multi-stage modeling outputs as .csv files.\n\ninputs:\n\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-the-Solvers","page":"Solver Configurations","title":"Configuring the Solvers","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_solver.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_solver-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_solver","text":"configure_solver(solver_settings_path::String, optimizer::Any)\n\nThis method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\\_model() method.\n\nArguments\n\nsolver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.\noptimizer::Any: the optimizer instance to be configured.\n\nCurrently supported solvers include: \"Gurobi\", \"CPLEX\", \"Clp\", \"Cbc\", or \"SCIP\"\n\nReturns\n\noptimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#GenX.infer_solver-Tuple{Any}","page":"Solver Configurations","title":"GenX.infer_solver","text":"infer_solver(optimizer::Any)\n\nReturn the name (String) of the solver to be used in the GenX.configure_solver method according to the solver imported by the user. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#GenX.rename_keys-Tuple{Dict, Dict}","page":"Solver Configurations","title":"GenX.rename_keys","text":"rename_keys(attributes:Dict, new_key_names::Dict)\n\nRenames the keys of the attributes dictionary based on old->new pairs in the newkeynames dictionary.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-HiGHS","page":"Solver Configurations","title":"Configuring HiGHS","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_highs.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_highs-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_highs","text":"configure_highs(solver_settings_path::String)\n\nReads user-specified solver settings from highs_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes HiGHS optimizer instance to be used in the GenX.generate_model() method.\n\nThe HiGHS optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided: \tAll the references are in https://github.com/jump-dev/HiGHS.jl, https://github.com/ERGO-Code/HiGHS, and https://highs.dev/\n\n# HiGHS Solver Parameters\n# Common solver settings\nFeasib_Tol: 1.0e-06 # Primal feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]\nOptimal_Tol: 1.0e-03 # Dual feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]\nTimeLimit: Inf # Time limit # [type: double, advanced: false, range: [0, inf], default: inf]\nPre_Solve: choose # Presolve option: \"off\", \"choose\" or \"on\" # [type: string, advanced: false, default: \"choose\"]\nMethod: ipm #choose #HiGHS-specific solver settings # Solver option: \"simplex\", \"choose\" or \"ipm\" # [type: string, advanced: false, default: \"choose\"] In order to run a case when the UCommit is set to 1, i.e. MILP instance, set the Method to choose\n\n#HiGHS-specific solver settings\n# Parallel option: \"off\", \"choose\" or \"on\"\n# [type: string, advanced: false, default: \"choose\"]\nparallel: choose\n\n# Compute cost, bound, RHS and basic solution ranging: \"off\" or \"on\"\n# [type: string, advanced: false, default: \"off\"]\nranging: off\n\n# Limit on cost coefficient: values larger than this will be treated as infinite\n# [type: double, advanced: false, range: [1e+15, inf], default: 1e+20]\ninfinite_cost: 1e+20\n\n# Limit on |constraint bound|: values larger than this will be treated as infinite\n# [type: double, advanced: false, range: [1e+15, inf], default: 1e+20]\ninfinite_bound: 1e+20\n\n# Lower limit on |matrix entries|: values smaller than this will be treated as zero\n# [type: double, advanced: false, range: [1e-12, inf], default: 1e-09]\nsmall_matrix_value: 1e-09\n\n# Upper limit on |matrix entries|: values larger than this will be treated as infinite\n# [type: double, advanced: false, range: [1, inf], default: 1e+15]\nlarge_matrix_value: 1e+15\n\n# IPM optimality tolerance\n# [type: double, advanced: false, range: [1e-12, inf], default: 1e-08]\nipm_optimality_tolerance: 1e-08\n\n# Objective bound for termination\n# [type: double, advanced: false, range: [-inf, inf], default: inf]\nobjective_bound: Inf\n\n# Objective target for termination\n# [type: double, advanced: false, range: [-inf, inf], default: -inf]\nobjective_target: -Inf\n\n# random seed used in HiGHS\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 0]\nrandom_seed: 0\n\n# number of threads used by HiGHS (0: automatic)\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 0]\nthreads: 0\n\n# Debugging level in HiGHS\n# [type: HighsInt, advanced: false, range: {0, 3}, default: 0]\nhighs_debug_level: 0\n\n# Analysis level in HiGHS\n# [type: HighsInt, advanced: false, range: {0, 63}, default: 0]\nhighs_analysis_level: 0\n\n# Strategy for simplex solver 0 => Choose; 1 => Dual (serial); 2 => Dual (PAMI); 3 => Dual (SIP); 4 => Primal\n# [type: HighsInt, advanced: false, range: {0, 4}, default: 1]\nsimplex_strategy: 1\n\n# Simplex scaling strategy: off / choose / equilibration / forced equilibration / max value 0 / max value 1 (0/1/2/3/4/5)\n# [type: HighsInt, advanced: false, range: {0, 5}, default: 1]\nsimplex_scale_strategy: 1\n\n# Strategy for simplex crash: off / LTSSF / Bixby (0/1/2)\n# [type: HighsInt, advanced: false, range: {0, 9}, default: 0]\nsimplex_crash_strategy: 0\n\n# Strategy for simplex dual edge weights: Choose / Dantzig / Devex / Steepest Edge (-1/0/1/2)\n# [type: HighsInt, advanced: false, range: {-1, 2}, default: -1]\nsimplex_dual_edge_weight_strategy: -1\n\n# Strategy for simplex primal edge weights: Choose / Dantzig / Devex / Steepest Edge (-1/0/1/2)\n# [type: HighsInt, advanced: false, range: {-1, 2}, default: -1]\nsimplex_primal_edge_weight_strategy: -1\n\n# Iteration limit for simplex solver\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nsimplex_iteration_limit: 2147483647\n\n# Limit on the number of simplex UPDATE operations\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 5000]\nsimplex_update_limit: 5000\n\n# Iteration limit for IPM solver\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nipm_iteration_limit: 2147483647\n\n# Minimum level of concurrency in parallel simplex\n# [type: HighsInt, advanced: false, range: {1, 8}, default: 1]\nsimplex_min_concurrency: 1\n\n# Maximum level of concurrency in parallel simplex\n# [type: HighsInt, advanced: false, range: {1, 8}, default: 8]\nsimplex_max_concurrency: 8\n\n# Enables or disables solver output\n# [type: bool, advanced: false, range: {false, true}, default: true]\noutput_flag: true\n\n# Enables or disables console logging\n# [type: bool, advanced: false, range: {false, true}, default: true]\nlog_to_console: true\n\n# Solution file\n# [type: string, advanced: false, default: \"\"]\nsolution_file: \"\"\n\n# Log file\n# [type: string, advanced: false, default: \"\"]\nlog_file: \"\"\n\n# Write the primal and dual solution to a file\n# [type: bool, advanced: false, range: {false, true}, default: false]\nwrite_solution_to_file: false\n\n# Write the solution in style: 0=>Raw (computer-readable); 1=>Pretty (human-readable) \n# [type: HighsInt, advanced: false, range: {0, 2}, default: 0]\nwrite_solution_style: 0\n\n# Write model file\n# [type: string, advanced: false, default: \"\"]\nwrite_model_file: \"\"\n\n# Write the model to a file\n# [type: bool, advanced: false, range: {false, true}, default: false]\nwrite_model_to_file: false\n\n# Whether symmetry should be detected\n# [type: bool, advanced: false, range: {false, true}, default: true]\nmip_detect_symmetry: true\n\n# MIP solver max number of nodes\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nmip_max_nodes: 2147483647\n\n# MIP solver max number of nodes where estimate is above cutoff bound\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nmip_max_stall_nodes: 2147483647\n\n# MIP solver max number of leave nodes\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nmip_max_leaves: 2147483647\n\n# limit on the number of improving solutions found to stop the MIP solver prematurely\n# [type: HighsInt, advanced: false, range: {1, 2147483647}, default: 2147483647]\nmip_max_improving_sols: 2147483647\n\n# maximal age of dynamic LP rows before they are removed from the LP relaxation\n# [type: HighsInt, advanced: false, range: {0, 32767}, default: 10]\nmip_lp_age_limit: 10\n\n# maximal age of rows in the cutpool before they are deleted\n# [type: HighsInt, advanced: false, range: {0, 1000}, default: 30]\nmip_pool_age_limit: 30\n\n# soft limit on the number of rows in the cutpool for dynamic age adjustment\n# [type: HighsInt, advanced: false, range: {1, 2147483647}, default: 10000]\nmip_pool_soft_limit: 10000\n\n# minimal number of observations before pseudo costs are considered reliable\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 8]\nmip_pscost_minreliable: 8\n\n# minimal number of entries in the cliquetable before neighborhood queries of the conflict graph use parallel processing\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 100000]\nmip_min_cliquetable_entries_for_parallelism: 100000\n\n# MIP solver reporting level\n# [type: HighsInt, advanced: false, range: {0, 2}, default: 1]\nmip_report_level: 1\n\n# MIP feasibility tolerance\n# [type: double, advanced: false, range: [1e-10, inf], default: 1e-06]\nmip_feasibility_tolerance: 1e-06\n\n# effort spent for MIP heuristics\n# [type: double, advanced: false, range: [0, 1], default: 0.05]\nmip_heuristic_effort: 0.05\n\n# tolerance on relative gap, |ub-lb|/|ub|, to determine whether optimality has been reached for a MIP instance\n# [type: double, advanced: false, range: [0, inf], default: 0.0001]\nmip_rel_gap: 0.0001\n\n# tolerance on absolute gap of MIP, |ub-lb|, to determine whether optimality has been reached for a MIP instance\n# [type: double, advanced: false, range: [0, inf], default: 1e-06]\nmip_abs_gap: 1e-06\n\n# Output development messages: 0 => none; 1 => info; 2 => verbose\n# [type: HighsInt, advanced: true, range: {0, 3}, default: 0]\nlog_dev_level: 0\n\n# Run the crossover routine for IPX\n# [type: string, advanced: \"on\", range: {\"off\", \"on\"}, default: \"off\"]\nrun_crossover: \"off\"\n\n# Allow ModelStatus::kUnboundedOrInfeasible\n# [type: bool, advanced: true, range: {false, true}, default: false]\nallow_unbounded_or_infeasible: false\n\n# Use relaxed implied bounds from presolve\n# [type: bool, advanced: true, range: {false, true}, default: false]\nuse_implied_bounds_from_presolve: false\n\n# Prevents LP presolve steps for which postsolve cannot maintain a basis\n# [type: bool, advanced: true, range: {false, true}, default: true]\nlp_presolve_requires_basis_postsolve: true\n\n# Use the free format MPS file reader\n# [type: bool, advanced: true, range: {false, true}, default: true]\nmps_parser_type_free: true\n\n# For multiple N-rows in MPS files: delete rows / delete entries / keep rows (-1/0/1)\n# [type: HighsInt, advanced: true, range: {-1, 1}, default: -1]\nkeep_n_rows: -1\n\n# Scaling factor for costs\n# [type: HighsInt, advanced: true, range: {-20, 20}, default: 0]\ncost_scale_factor: 0\n\n# Largest power-of-two factor permitted when scaling the constraint matrix\n# [type: HighsInt, advanced: true, range: {0, 30}, default: 20]\nallowed_matrix_scale_factor: 20\n\n# Largest power-of-two factor permitted when scaling the costs\n# [type: HighsInt, advanced: true, range: {0, 20}, default: 0]\nallowed_cost_scale_factor: 0\n\n# Strategy for permuting before simplex\n# [type: HighsInt, advanced: true, range: {-1, 1}, default: -1]\nsimplex_permute_strategy: -1\n\n# Max level of dual simplex cleanup\n# [type: HighsInt, advanced: true, range: {0, 2147483647}, default: 1]\nmax_dual_simplex_cleanup_level: 1\n\n# Max level of dual simplex phase 1 cleanup\n# [type: HighsInt, advanced: true, range: {0, 2147483647}, default: 2]\nmax_dual_simplex_phase1_cleanup_level: 2\n\n# Strategy for PRICE in simplex\n# [type: HighsInt, advanced: true, range: {0, 3}, default: 3]\nsimplex_price_strategy: 3\n\nStrategy for solving unscaled LP in simplex\n[type: HighsInt, advanced: true, range: {0, 2}, default: 1]\nsimplex_unscaled_solution_strategy: 1\n\nPerform initial basis condition check in simplex\n[type: bool, advanced: true, range: {false, true}, default: true]\nsimplex_initial_condition_check: true\n\nNo unnecessary refactorization on simplex rebuild\n[type: bool, advanced: true, range: {false, true}, default: true]\nno_unnecessary_rebuild_refactor: true\n\nTolerance on initial basis condition in simplex\n[type: double, advanced: true, range: [1, inf], default: 1e+14]\nsimplex_initial_condition_tolerance: 1e+14\n\nTolerance on solution error when considering refactorization on simplex rebuild\n[type: double, advanced: true, range: [-inf, inf], default: 1e-08]\nrebuild_refactor_solution_error_tolerance: 1e-08\n\nTolerance on dual steepest edge weight errors\n[type: double, advanced: true, range: [0, inf], default: inf]\ndual_steepest_edge_weight_error_tolerance: Inf\n\nThreshold on dual steepest edge weight errors for Devex switch\n[type: double, advanced: true, range: [1, inf], default: 10]\ndual_steepest_edge_weight_log_error_threshold: 10.0\n\nDual simplex cost perturbation multiplier: 0 => no perturbation\n[type: double, advanced: true, range: [0, inf], default: 1]\ndual_simplex_cost_perturbation_multiplier: 1.0\n\nPrimal simplex bound perturbation multiplier: 0 => no perturbation\n[type: double, advanced: true, range: [0, inf], default: 1]\nprimal_simplex_bound_perturbation_multiplier: 1.0\n\nDual simplex pivot growth tolerance\n[type: double, advanced: true, range: [1e-12, inf], default: 1e-09]\ndual_simplex_pivot_growth_tolerance: 1e-09\n\nMatrix factorization pivot threshold for substitutions in presolve\n[type: double, advanced: true, range: [0.0008, 0.5], default: 0.01]\npresolve_pivot_threshold: 0.01\n\nMaximal fillin allowed for substitutions in presolve\n[type: HighsInt, advanced: true, range: {0, 2147483647}, default: 10]\npresolve_substitution_maxfillin: 10\n\nMatrix factorization pivot threshold\n[type: double, advanced: true, range: [0.0008, 0.5], default: 0.1]\nfactor_pivot_threshold: 0.1\n\nMatrix factorization pivot tolerance\n[type: double, advanced: true, range: [0, 1], default: 1e-10]\nfactor_pivot_tolerance: 1e-10\n\nTolerance to be satisfied before IPM crossover will start\n[type: double, advanced: true, range: [1e-12, inf], default: 1e-08]\nstart_crossover_tolerance: 1e-08\n\nUse original HFactor logic for sparse vs hyper-sparse TRANs\n[type: bool, advanced: true, range: {false, true}, default: true]\nuse_original_HFactor_logic: true\n\nCheck whether LP is candidate for LiDSE\n[type: bool, advanced: true, range: {false, true}, default: true]\nless_infeasible_DSE_check: true\n\nUse LiDSE if LP has right properties\n[type: bool, advanced: true, range: {false, true}, default: true]\nless_infeasible_DSE_choose_row: true\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-Gurobi","page":"Solver Configurations","title":"Configuring Gurobi","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_gurobi.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_gurobi-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_gurobi","text":"configure_gurobi(solver_settings_path::String)\n\nReads user-specified solver settings from gurobi_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes Gurobi optimizer instance to be used in the GenX.generate_model() method.\n\nThe Gurobi optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nFeasibilityTol = 1e-6 (Constraint (primal) feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/feasibilitytol.html)\nOptimalityTol = 1e-4 (Dual feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/optimalitytol.html#parameter:OptimalityTol)\nPresolve = -1 (Controls presolve level. See https://www.gurobi.com/documentation/8.1/refman/presolve.html)\nAggFill = -1 (Allowed fill during presolve aggregation. See https://www.gurobi.com/documentation/8.1/refman/aggfill.html#parameter:AggFill)\nPreDual = -1 (Presolve dualization. See https://www.gurobi.com/documentation/8.1/refman/predual.html#parameter:PreDual)\nTimeLimit = Inf\t(Limits total time solver. See https://www.gurobi.com/documentation/8.1/refman/timelimit.html)\nMIPGap = 1e-4 (Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). See https://www.gurobi.com/documentation/8.1/refman/mipgap2.html)\nCrossover = -1 (Barrier crossver strategy. See https://www.gurobi.com/documentation/8.1/refman/crossover.html#parameter:Crossover)\nMethod = -1\t(Algorithm used to solve continuous models (including MIP root relaxation). See https://www.gurobi.com/documentation/8.1/refman/method.html)\nBarConvTol = 1e-8 (Barrier convergence tolerance (determines when barrier terminates). See https://www.gurobi.com/documentation/8.1/refman/barconvtol.html)\nNumericFocus = 0 (Numerical precision emphasis. See https://www.gurobi.com/documentation/8.1/refman/numericfocus.html)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-CPLEX","page":"Solver Configurations","title":"Configuring CPLEX","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_cplex.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_cplex-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_cplex","text":"configure_cplex(solver_settings_path::String)\n\nReads user-specified solver settings from cplex_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes CPLEX optimizer instance.\n\nThe optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nFeasib_Tol,\nsets CPX_PARAM_EPRHS. Control the primal feasibility tolerance. Default is 1e-6.\nOptimal_Tol,\nsets CPX_PARAM_EPOPT. Control the optimality tolerance. Default is 1e-4.\nAggFill,\nsets CPX_PARAM_AGGFILL. Control the allowed fill during presolve aggregation. Default is 10.\nPreDual,\nsets CPX_PARAM_PREDUAL. Decides whether presolve should pass the primal or dual linear programming problem to the LP optimization algorithm. Default is 0.\nTimeLimit,\nsets CPX_PARAM_TILIM. Limits total solver time. Default is 1e+75.\nMIPGap,\nsets CPX_PARAM_EPGAP Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). Default is 1e-3.\nMethod,\nsets CPX_PARAM_LPMETHOD. Algorithm used to solve continuous models (including MIP root relaxation) Default is 0.\nBarConvTol,\nsets CPX_PARAM_BAREPCOMP. Barrier convergence tolerance (determines when barrier terminates). Default is 1e-8.\nNumericFocus,\nsets CPX_PARAM_NUMERICALEMPHASIS. Numerical precision emphasis. Default is 0.\nBarObjRng,\nsets CPX_PARAM_BAROBJRNG. The maximum absolute value of the objective function. Default is 1e+75.\nSolutionType,\nsets CPX_PARAM_SOLUTIONTYPE. Solution type for LP or QP. Default is 2.\n\nThe optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nAny other attributes in the settings file (which typically start with CPX_PARAM_) will also be passed to the solver.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-Clp","page":"Solver Configurations","title":"Configuring Clp","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_clp.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_clp-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_clp","text":"configure_clp(solver_settings_path::String)\n\nReads user-specified solver settings from clp_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes Clp optimizer instance to be used in the GenX.generate_model() method.\n\nThe Clp optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nPrimalTolerance = 1e-7 (Primal feasibility tolerance)\nDualTolerance = 1e-7 (Dual feasibility tolerance)\nDualObjectiveLimit = 1e308 (When using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit)\nMaximumIterations = 2147483647 (Terminate after performing this number of simplex iterations)\nMaximumSeconds = -1.0\t(Terminate after this many seconds have passed. A negative value means no time limit)\nLogLevel = 1 (Set to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output)\nPresolveType = 0 (Set to 1 to disable presolve)\nSolveType = 5 (Solution method: dual simplex (0), primal simplex (1), sprint (2), barrier with crossover (3), barrier without crossover (4), automatic (5))\nInfeasibleReturn = 0 (Set to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well))\nScaling = 3 (0 0ff, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic (later))\nPerturbation = 100 (switch on perturbation (50), automatic (100), don't try perturbing (102))\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-Cbc","page":"Solver Configurations","title":"Configuring Cbc","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_cbc.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_cbc-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_cbc","text":"configure_cbc(solver_settings_path::String)\n\nReads user-specified solver settings from cbc_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes Cbc optimizer instance to be used in the GenX.generate_model() method.\n\nThe Cbc optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nseconds = 1e-6\nlogLevel = 1e-6\nmaxSolutions = -1\nmaxNodes = -1\nallowableGap = -1\nratioGap = Inf\nthreads = 1\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-SCIP","page":"Solver Configurations","title":"Configuring SCIP","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_scip.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_scip-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_scip","text":"configure_scip(solver_settings_path::String)\n\nReads user-specified solver settings from scip_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes SCIP optimizer instance to be used in the GenX.generate_model() method.\n\nThe SCIP optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nDispverblevel = 0\nlimitsgap = 0.05\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/policies/#Emission-mitigation-policies","page":"Policies","title":"Emission mitigation policies","text":"","category":"section"},{"location":"Model_Reference/policies/#Capacity-Reserve-Margin","page":"Policies","title":"Capacity Reserve Margin","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.cap_reserve_margin!","category":"page"},{"location":"Model_Reference/policies/#GenX.cap_reserve_margin!","page":"Policies","title":"GenX.cap_reserve_margin!","text":"cap_reserve_margin!(EP::Model, inputs::Dict, setup::Dict)\n\nInstead of modeling capacity reserve margin requirement (a.k.a. capacity market or resource adequacy requirement) using an annual constraint, we model each requirement with hourly constraint by simulating the activation of the capacity obligation. We define capacity reserve margin constraint for subsets of zones, z in mathcalZ^CRM_p, and each subset stands for a locational deliverability area (LDA) or a reserve sharing group. For thermal resources, the available capacity is the total capacity in the LDA derated by the outage rate, epsilon_yzp^CRM. For variable renewable energy (y in mathcalVRE), the available capacity is the maximum discharge potential in time step t derated by the derating factor. For standalone storage and co-located VRE and storage resources (y in mathcalO cup mathcalVS) the available capacity is the net injection into the transmission network plus the net virtual injection corresponding to charge held in reserve, derated by the derating factor. For information on how each component contributes to the capacity reserve margin formulation for co-located VRE and storage resources, see vre_stor_capres!(). For flexible demand resources (y in mathcalDF), the available capacity is the net injection into the transmission network in time step t derated by the derating factor, also stored in the parameter, epsilon_yzp^CRM. If the imported capacity is eligible to provide capacity to the CRM constraint, the inbound powerflow on all lines mathcalL_p^in in time step t will be derated to form the available capacity from outside of the LDA. The reverse is true as well: the outbound derated powerflow on all lines mathcalL_p^out in time step t is taken out from the total available capacity. The derating factor should be equal to the expected availability of the resource during periods when the capacity reserve constraint is binding (e.g. accounting for forced outages during supply constrained periods) and is similar to derating factors used in the capacity markets. On top of the flexible demand resources, demand curtailment can also provide capacity (i.e., demand response or load management). We allow all segments of voluntary demand curtailment, s geq 2 in S, to contribute to capacity requirements. The first segment s = 1 in S corresponds to involuntary demand curtailment or emergency load shedding at the price cap or value of lost demand, and thus does not contribute to reserve requirements. Note that the time step-weighted sum of the shadow prices of this constraint corresponds to the capacity market payments reported by ISOs with mandate capacity market mechanism.\n\nbeginaligned\n\t sum_z in mathcalZ^CRM_p Big( sum_y in mathcalH epsilon_yzp^CRM times Delta^texttotal_yz + sum_y in mathcalVRE epsilon_yzp^CRM times rho^max_yzt \n\t + sum_y in mathcalO epsilon_yzp^CRM times left(Theta_yzt + Theta^CRM_ozt - Pi^CRM_ozt - Pi_yzt right) + sum_y in mathcalDF epsilon_yzp^CRM times left(Pi_yzt - Theta_yzt right) \n\t + sum_y in mathcalVS^pv (epsilon_yzp^CRM times eta^inverter_yz times rho^maxpv_yzt times Delta^totalpv_yz) \n\t + sum_y in mathcalVS^wind (epsilon_yzp^CRM times rho^maxwind_yzt times Delta^totalwind_yz) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis (epsilon_yzp^CRM times eta^inverter_yz times (Theta^dc_yzt + Theta^CRMdc_yzt)) \n + sum_y in mathcalVS^symac cup mathcalVS^asymacdis (epsilon_yzp^CRM times (Theta^ac_yzt + Theta^CRMac_yzt)) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times fracPi^dc_yzt + Pi^CRMdc_yzteta^inverter_yz) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times (Pi^ac_yzt + Pi^CRMac_yzt)) \n\t + sum_l in mathcalL_p^in epsilon_yzp^CRM times Phi_lt - sum_l in mathcalL_p^out epsilon_yzp^CRM times Phi_lt\n \t+ sum_s geq 2 Lambda_stz Big) \n \t geq sum_z in mathcalZ^CRM_p left( left(1 + RM_zp^CRM right) times D_zt right) hspace1 cm forall t in mathcalT forall pin mathcalP^CRM\nendaligned\n\nNote that multiple capacity reserve margin requirements can be specified covering different individual zones or aggregations of zones, where the total number of constraints is specified by the GenX settings parameter CapacityReserveMargin (where this parameter should be an integer value > 0). The expressions establishing the capacity reserve margin contributions of each technology class are included in their respective technology modules.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#CO_2-Constraint-Policy","page":"Policies","title":"CO_2 Constraint Policy","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.co2_cap!","category":"page"},{"location":"Model_Reference/policies/#GenX.co2_cap!","page":"Policies","title":"GenX.co2_cap!","text":"co2_cap!(EP::Model, inputs::Dict, setup::Dict)\n\nThis policy constraints mimics the CO_2 emissions cap and permit trading systems, allowing for emissions trading across each zone for which the cap applies. The constraint p in mathcalP^CO_2 can be flexibly defined for mass-based or rate-based emission limits for one or more model zones, where zones can trade CO_2 emissions permits and earn revenue based on their CO_2 allowance. Note that if the model is fully linear (e.g. no unit commitment or linearized unit commitment), the dual variable of the emissions constraints can be interpreted as the marginal CO_2 price per tonne associated with the emissions target. Alternatively, for integer model formulations, the marginal CO_2 price can be obtained after solving the model with fixed integer/binary variables.\n\nThe CO_2 emissions limit can be defined in one of the following ways: a) a mass-based limit defined in terms of annual CO_2 emissions budget (in million tonnes of CO2), b) a demand-side rate-based limit defined in terms of tonnes CO_2 per MWh of fulfilled demand and c) a generation-side rate-based limit defined in terms of tonnes CO_2 per MWh of generation.\n\nMass-based emissions constraint\n\nMass-based emission limits are implemented in the following expression. For each constraint, p in mathcalP^CO_2_mass, we define a set of zones z in mathcalZ^CO_2_pmass that can trade CO_2 allowance. Input data for each constraint p in mathcalP^CO_2_mass requires the CO_2 allowance/ budget for each model zone, epsilon^CO_2_zp mass, to be provided in terms of million metric tonnes. For every generator y, the parameter epsilon_yz^CO_2 reflects the specific CO_2 emission intensity in tCO_2/MWh associated with its operation. The resulting constraint is given as:\n\nbeginaligned\n sum_z in mathcalZ^CO_2_pmass sum_y in mathcalG sum_t in mathcalT left(epsilon_yz^CO_2 times omega_t times Theta_yzt right)\n leq sum_z in mathcalZ^CO_2_pmass epsilon^CO_2_zp mass hspace1 cm forall p in mathcalP^CO_2_mass\nendaligned\n\nIn the above constraint, we include both power discharge and charge term for each resource to account for the potential for CO_2 emissions (or removal when considering negative emissions technologies) associated with each step. Note that if a limit is applied to each zone separately, then the set mathcalZ^CO_2_pmass will contain only one zone with no possibility of trading. If a system-wide emission limit constraint is applied, then mathcalZ^CO_2_pmass will be equivalent to a set of all zones.\n\nDemand-side rate-based emissions constraint\n\nWe modify the right hand side of the above mass-based constraint, p in mathcalP^CO_2_demand, to set emissions target based on a CO_2 emission rate limit in tCO_2/MWh times the total demand served (fulfilled) in each zone. In the following constraint, total demand served takes into account non-served energy and storage related losses. Here, epsilon_zpdemand^maxCO_2 denotes the emission limit in terms on tCO_2/MWh.\n\nbeginaligned\n sum_z in mathcalZ^CO_2_pdemand sum_y in mathcalG sum_t in mathcalT left(epsilon_yz^CO_2 times omega_t times Theta_ytz right)\n leq sum_z in mathcalZ^CO_2_pdemand sum_t in mathcalT\n left(epsilon_zpdemand^CO_2 times omega_t times D_zt right) \n + sum_z in mathcalZ^CO_2_pdemand sum_y in mathcalO cup mathcalVS^stor sum_t in mathcalT\n left(epsilon_zpdemand^CO_2 times omega_t times left(Pi_ytz - Theta_ytz right) right) \n - sum_z in mathcalZ^CO_2_pdemand sum_s in mathcalS sum_t in mathcalT left(epsilon_zpdemand^CO_2 times omega_t times Lambda_sztright) hspace1 cm forall p in mathcalP^CO_2_demand\nendaligned\n\nGenerator-side emissions rate-based constraint\n\nSimilarly, a generation based emission constraint is defined by setting the emission limit based on the total generation times the carbon emission rate limit in tCO_2/MWh of the region. The resulting constraint is given as:\n\nbeginaligned\nsum_z in mathcalZ^CO_2_pgen sum_y in mathcalG sum_t in mathcalT left(epsilon_yz^CO_2 times omega_t times Theta_ytz right) \n leq sum_z in mathcalZ^CO_2_pgen sum_y in mathcalG sum_t in mathcalT left(epsilon_zpgen^CO_2 times omega_t times Theta_ytz right) hspace1 cm forall p in mathcalP^CO_2_gen\nendaligned\n\nNote that the generator-side rate-based constraint can be used to represent a fee-rebate (``feebate'') system: the dirty generators that emit above the bar (epsilon_zpgen^maxCO_2) have to buy emission allowances from the emission regulator in the region z where they are located; in the same vein, the clean generators get rebates from the emission regulator at an emission allowance price being the dual variable of the emissions rate constraint.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#Energy-Share-Requirement","page":"Policies","title":"Energy Share Requirement","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.load_energy_share_requirement!\nGenX.energy_share_requirement!","category":"page"},{"location":"Model_Reference/policies/#GenX.load_energy_share_requirement!","page":"Policies","title":"GenX.load_energy_share_requirement!","text":"load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#GenX.energy_share_requirement!","page":"Policies","title":"GenX.energy_share_requirement!","text":"energy_share_requirement!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function establishes constraints that can be flexibily applied to define alternative forms of policies that require generation of a minimum quantity of megawatt-hours from a set of qualifying resources, such as renewable portfolio standard (RPS) or clean electricity standard (CES) policies prevalent in different jurisdictions. These policies usually require that the annual MWh generation from a subset of qualifying generators has to be higher than a pre-specified percentage of demand from qualifying zones. The implementation allows for user to define one or multiple RPS/CES style minimum energy share constraints, where each constraint can cover different combination of model zones to mimic real-world policy implementation (e.g. multiple state policies, multiple RPS tiers or overlapping RPS and CES policies). The number of energy share requirement constraints is specified by the user by the value of the GenX settings parameter EnergyShareRequirement (this value should be an integer >=0). For each constraint p in mathcalP^ESR, we define a subset of zones z in mathcalZ^ESR_p subset mathcalZ that are eligible for trading renewable/clean energy credits to meet the corresponding renewable/clean energy requirement. For each energy share requirement constraint p in mathcalP^ESR, we specify the share of total demand in each eligible model zone, z in mathcalZ^ESR_p, that must be served by qualifying resources, mathcalG_p^ESR subset mathcalG:\n\nbeginaligned\nsum_z in mathcalZ_p^ESR sum_y in mathcalG_p^ESR sum_t in mathcalT (omega_t times Theta_yzt) geq sum_z in mathcalZ^ESR_p sum_t in mathcalT (mu_pz^ESR times omega_t times D_zt) + \nsum_y in mathcalVS^stor sum_z in mathcalZ^ESR_p sum_t in mathcalT left(mu_pz^ESR times omega_t times (fracPi^dc_yzteta_yz^inverter + Pi^ac_yzt - eta_yz^inverter times Theta^dc_yzt - Theta^ac_yzt) right) + \nsum_y in mathcalO sum_z in mathcalZ^ESR_p sum_t in mathcalT left(mu_pz^ESR times omega_t times (Pi_yzt - Theta_yzt) right) hspace1 cm forall p in mathcalP^ESR \nendaligned\n\nThe final two terms in the summation above adds roundtrip storage losses to the total demand to which the energy share obligation applies. This term is included in the constraint if the GenX setup parameter StorageLosses=1. If StorageLosses=0, this term is removed from the constraint. In practice, most existing renewable portfolio standard policies do not account for storage losses when determining energy share requirements. However, with 100% RPS or CES policies enacted in several jurisdictions, policy makers may wish to include storage losses in the minimum energy share, as otherwise there will be a difference between total generation and total demand that will permit continued use of non-qualifying resources (e.g. emitting generators).\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#Minimum-Capacity-Requirement","page":"Policies","title":"Minimum Capacity Requirement","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.minimum_capacity_requirement!","category":"page"},{"location":"Model_Reference/policies/#GenX.minimum_capacity_requirement!","page":"Policies","title":"GenX.minimum_capacity_requirement!","text":"minimum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)\n\nThe minimum capacity requirement constraint allows for modeling minimum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement p in mathcalP^MinCapReq, we model the policy with the following constraint.\n\nbeginaligned\nsum_y in mathcalG sum_z in mathcalZ left( epsilon_yzp^MinCapReq times Delta^texttotal_yz right) geq REQ_p^MinCapReq hspace1 cm forall p in mathcalP^MinCapReq\nendaligned\n\nNote that epsilon_yzp^MinCapReq is the eligiblity of a generator of technology y in zone z of requirement p and will be equal to 1 for eligible generators and will be zero for ineligible resources. The dual value of each minimum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.\n\nAlso note that co-located VRE and storage resources, there are three different components \tthat minimum capacity requirements can be created for. The capacity of solar PV (in AC terms \tsince the capacity is multiplied by the inverter efficiency), the capacity of wind, and the discharge \tcapacity of storage (power to energy ratio times the energy capacity) can all have minimum capacity \trequirements.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#Maximum-Capacity-Requirement","page":"Policies","title":"Maximum Capacity Requirement","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"Modules = [GenX]\nPages = [\"maximum_capacity_requirement.jl\"]","category":"page"},{"location":"Model_Reference/policies/#GenX.load_maximum_capacity_requirement!-Tuple{AbstractString, Dict, Dict}","page":"Policies","title":"GenX.load_maximum_capacity_requirement!","text":"load_maximum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)\n\nRead input parameters related to maximum capacity requirement constraints (e.g. technology specific deployment mandates)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/policies/#GenX.maximum_capacity_requirement!-Tuple{JuMP.Model, Dict, Dict}","page":"Policies","title":"GenX.maximum_capacity_requirement!","text":"maximum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)\n\nThe maximum capacity requirement constraint allows for modeling maximum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement p in mathcalP^MaxCapReq, we model the policy with the following constraint.\n\nbeginaligned\nsum_y in mathcalG sum_z in mathcalZ left( epsilon_yzp^MaxCapReq times Delta^texttotal_yz right) leq REQ_p^MaxCapReq hspace1 cm forall p in mathcalP^MaxCapReq\nendaligned\n\nNote that epsilon_yzp^MaxCapReq is the eligiblity of a generator of technology y in zone z of requirement p and will be equal to 1 for eligible generators and will be zero for ineligible resources. The dual value of each maximum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.\n\n\n\n\n\n","category":"method"},{"location":"limitations_genx/#Limitations-of-the-GenX-Model","page":"Limitation of GenX","title":"Limitations of the GenX Model","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"While the benefits of an openly available generation and transmission expansion model are high, many approximations have been made due to missing data or to manage computational tractability. The assumptions of the GenX model are listed below. It serves as a caveat to the user and as an encouragement to improve the approximations.","category":"page"},{"location":"limitations_genx/#1.-Time-period","page":"Limitation of GenX","title":"1. Time period","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX makes the simplifying assumption that each time period contains n copies of a single, representative year. GenX optimizes generation and transmission capacity for just this characteristic year within each time period, assuming the results for different years in the same time period are identical. However, the GenX objective function accounts only for the cost of the final model time period.","category":"page"},{"location":"limitations_genx/#2.-Cost","page":"Limitation of GenX","title":"2. Cost","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"The GenX objective function assumes that the cost of powerplants is specified in the unit of currency per unit of capacity. GenX also assumes that the capital cost of technologies is paid through loans.","category":"page"},{"location":"limitations_genx/#3.Market","page":"Limitation of GenX","title":"3.Market","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX is a bottom-up (technology-explicit), partial equilibrium model that assumes perfect markets for commodities. In other words, each commodity is produced such that the sum of producer and consumer surplus is maximized.","category":"page"},{"location":"limitations_genx/#4.-Technology","page":"Limitation of GenX","title":"4. Technology","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"Behavioral response and acceptance of new technology are often modeled simplistically as a discount rate or by externally fixing the technology capacity. A higher, technology-specific discount rate represents consumer reluctance to accept newer technologies.","category":"page"},{"location":"limitations_genx/#5.-Uncertainty","page":"Limitation of GenX","title":"5. Uncertainty","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"Because each model realization assumes a particular state of the world based on the input values drawn, the parameter uncertainty is propagated through the model in the case of myopic model runs.","category":"page"},{"location":"limitations_genx/#6.-Decision-making","page":"Limitation of GenX","title":"6. Decision-making","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX assumes rational decision making, with perfect information and perfect foresight, and simultaneously optimizes all decisions over the user-specified time horizon.","category":"page"},{"location":"limitations_genx/#7.-Demand","page":"Limitation of GenX","title":"7. Demand","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX assumes price-elastic demand segments that are represented using piece-wise approximation rather than an inverse demand curve to keep the model linear.","category":"page"},{"location":"Public_API/public_api/#Public-Documentation","page":"Public API","title":"Public Documentation","text":"","category":"section"},{"location":"Public_API/public_api/","page":"Public API","title":"Public API","text":"Documentation for GenX public interface.","category":"page"},{"location":"Public_API/public_api/","page":"Public API","title":"Public API","text":"GenX.run_genx_case!\nGenX.configure_settings\nGenX.configure_solver\nGenX.load_inputs\nGenX.load_dataframe\nGenX.generate_model\nGenX.solve_model\nGenX.write_outputs\nGenX.mga","category":"page"},{"location":"Public_API/public_api/#GenX.run_genx_case!","page":"Public API","title":"GenX.run_genx_case!","text":"run_genx_case!(case::AbstractString, optimizer::Any=HiGHS.Optimizer)\n\nRun a GenX case with the specified optimizer. The optimizer can be any solver supported by MathOptInterface.\n\nArguments\n\ncase::AbstractString: the path to the case folder\noptimizer::Any: the optimizer instance to be used in the optimization model\n\nExample\n\nrun_genx_case!(\"path/to/case\", HiGHS.Optimizer)\n\nrun_genx_case!(\"path/to/case\", Gurobi.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.configure_settings","page":"Public API","title":"GenX.configure_settings","text":"configure_settings(settings_path::String, output_settings_path::String)\n\nReads in the settings from the genx_settings.yml and output_settings.yml YAML files and merges them with the default settings. It then validates the settings and returns the settings dictionary.\n\nArguments\n\nsettings_path::String: The path to the settings YAML file.\noutput_settings_path::String: The path to the output settings YAML file.\n\nReturns\n\nsettings::Dict: The settings dictionary.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.configure_solver","page":"Public API","title":"GenX.configure_solver","text":"configure_solver(solver_settings_path::String, optimizer::Any)\n\nThis method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\\_model() method.\n\nArguments\n\nsolver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.\noptimizer::Any: the optimizer instance to be configured.\n\nCurrently supported solvers include: \"Gurobi\", \"CPLEX\", \"Clp\", \"Cbc\", or \"SCIP\"\n\nReturns\n\noptimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.load_inputs","page":"Public API","title":"GenX.load_inputs","text":"load_inputs(setup::Dict,path::AbstractString)\n\nLoads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function\n\ninputs: setup - dict object containing setup parameters path - string path to working directory\n\nreturns: Dict (dictionary) object containing all data inputs\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.load_dataframe","page":"Public API","title":"GenX.load_dataframe","text":"load_dataframe(path::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\nload_dataframe(dir::AbstractString, base::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.generate_model","page":"Public API","title":"GenX.generate_model","text":"generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAttributes,modeloutput = nothing)\n\nThis function sets up and solves a constrained optimization model of electricity system capacity expansion and operation problem and extracts solution variables for later processing.\n\nIn addition to calling a number of other modules to create constraints for specific resources, policies, and transmission assets, this function initializes two key expressions that are successively expanded in each of the resource-specific modules: (1) the objective function; and (2) the zonal power balance expression. These two expressions are the only expressions which link together individual modules (e.g. resources, transmission assets, policies), which otherwise are self-contained in defining relevant variables, expressions, and constraints.\n\nObjective Function\n\nThe objective function of GenX minimizes total annual electricity system costs over the following six components shown in the equation below:\n\nbeginaligned\n\tsum_y in mathcalG sum_z in mathcalZ\n\tleft( (pi^INVEST_yz times overlineOmega^size_yz times Omega_yz)\n\t+ (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right) + notag \n\tsum_y in mathcalO sum_z in mathcalZ\n\tleft( (pi^INVESTenergy_yz times Omega^energy_yz)\n\t+ (pi^FOMenergy_yz times Delta^totalenergy_yz)right) + notag \n\tsum_y in mathcalO^asym sum_z in mathcalZ\n\tleft( (pi^INVESTcharge_yz times Omega^charge_yz)\n\t+ (pi^FOMcharge_yz times Delta^totalcharge_yz)right) + notag \n\t sum_y in mathcalG sum_z in mathcalZ sum_t in mathcalT left( omega_ttimes(pi^VOM_yz + pi^FUEL_yz)times Theta_yztright) + sum_y in mathcalO cup DF sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMcharge_yz times Pi_yztright) +notag \n\tsum_s in mathcalS sum_z in mathcalZ sum_t in mathcalTleft(omega_t times n_s^slope times Lambda_sztright) + sum_t in mathcalT left(omega_t times pi^unmet_rsv times r^unmet_tright) notag \n\tsum_y in mathcalH sum_z in mathcalZ sum_t in mathcalTleft(omega_t times pi^START_yz times chi_sztright) + notag \n\t sum_l in mathcalLleft(pi^TCAP_l times bigtriangleupvarphi^max_lright)\nendaligned\n\nThe first summation represents the fixed costs of generation/discharge over all zones and technologies, which refects the sum of the annualized capital cost, pi^INVEST_yz, times the total new capacity added (if any), plus the Fixed O&M cost, pi^FOM_yz, times the net installed generation capacity, overlineOmega^size_yz times Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources. This term includes the sum of the annualized energy capital cost, pi^INVESTenergy_yz, times the total new energy capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed energy storage capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components (mathcalO^asym). This term includes the sum of the annualized charging power capital cost, pi^INVESTcharge_yz, times the total new charging power capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed charging power capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe fourth and fifth summations corresponds to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, pi^FUEL_yz (if any), plus variable O&M cost, pi^VOM_yz times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, yinmathcalDF) in time step t, Theta_yzt, and the weight of each time step t, omega_t, where omega_t is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, t such that the sum of omega_t forall t in T = 8760, approximating annual operating costs. The fifth summation represents the variable charging O&M cost, pi^VOMcharge_yz times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step t , Pi_yzt and the annual weight of time step t,omega_t.\n\nThe sixth summation represents the total cost of unserved demand across all segments s of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), n_s^slope, times the amount of non-served energy, Lambda_yzt, for each segment on each zone during each time step (weighted by omega_t).\n\nThe seventh summation represents the total cost of not meeting hourly operating reserve requirements, where pi^unmet_rsv is the cost penalty per unit of non-served reserve requirement, and r^unmet_t is the amount of non-served reserve requirement in each time step (weighted by omega_t).\n\nThe eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. y in mathcalUC), equal to the cost of start-up, pi^START_yz, times the number of startup events, chi_yzt, for the cluster of units in each zone and time step (weighted by omega_t).\n\nThe last term corresponds to the transmission reinforcement or construction costs, for each transmission line in the model. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, pi^TCAP_l, times the additional transmission capacity variable, bigtriangleupvarphi^max_l. Note that fixed O\\&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.\n\nIn summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions: (1) where and how to invest on capacity, (2) how to dispatch or operate that capacity, (3) which consumer demand segments to serve or curtail, (4) how to cycle and commit thermal units subject to unit commitment decisions, (5) and where and how to invest in additional transmission network capacity to increase power transfer capacity between zones. Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.\n\nPower Balance\n\nThe power balance constraint of the model ensures that electricity demand is met at every time step in each zone. As shown in the constraint, electricity demand, D_tz, at each time step and for each zone must be strictly equal to the sum of generation, Theta_yzt, from thermal technologies (mathcalH), curtailable VRE (mathcalVRE), must-run resources (mathcalMR), and hydro resources (mathcalW). At the same time, energy storage devices (mathcalO) can discharge energy, Theta_yzt to help satisfy demand, while when these devices are charging, Pi_yzt, they increase demand. For the case of flexible demand resources (mathcalDF), delaying demand (equivalent to charging virtual storage), Pi_yzt, decreases demand while satisfying delayed demand (equivalent to discharging virtual demand), Theta_yzt, increases demand. Price-responsive demand curtailment, Lambda_szt, also reduces demand. Finally, power flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign in the below constraint. At the same time losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see Transmission section).\n\nbeginaligned\n\t sum_yin mathcalHTheta_yzt +sum_yin mathcalVRETheta_yzt +sum_yin mathcalMRTheta_yzt + sum_yin mathcalO(Theta_yzt-Pi_yzt) + notag\n\t sum_yin mathcalDF(-Theta_yzt+Pi_yzt) +sum_yin mathcalWTheta_yzt+ notag\n\t+ sum_sin mathcalSLambda_szt - sum_lin mathcalL(varphi^map_lz times Phi_lt) -frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot)) = D_zt\n\tforall zin mathcalZ t in mathcalT\nendaligned\n\nArguments\n\nsetup::Dict: Dictionary containing the settings for the model.\ninputs::Dict: Dictionary containing the inputs for the model.\nOPTIMIZER::MOI.OptimizerWithAttributes: The optimizer to use for solving the model.\n\nReturns\n\nModel: The model object containing the entire optimization problem model to be solved by solve_model.jl\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.solve_model","page":"Public API","title":"GenX.solve_model","text":"solve_model(EP::Model, setup::Dict)\n\nDescription: Solves and extracts solution variables for later processing\n\nArguments\n\nEP::Model: a JuMP model representing the energy optimization problem\nsetup::Dict: a Dict containing GenX setup flags\n\nReturns\n\nEP::Model: the solved JuMP model\nsolver_time::Float64: time taken to solve the model\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.write_outputs","page":"Public API","title":"GenX.write_outputs","text":"write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nFunction for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.mga","page":"Public API","title":"GenX.mga","text":"mga(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nWe have implemented an updated Modeling to Generate Alternatives (MGA) Algorithm proposed by Berntsen and Trutnevyte (2017) to generate a set of feasible, near cost-optimal technology portfolios. This algorithm was developed by Brill Jr, E. D., 1979 and introduced to energy system planning by DeCarolia, J. F., 2011.\n\nTo create the MGA formulation, we replace the cost-minimizing objective function of GenX with a new objective function that creates multiple generation portfolios by zone. We further add a new budget constraint based on the optimal objective function value f^* of the least-cost model and the user-specified value of slack delta. After adding the slack constraint, the resulting MGA formulation is given as:\n\nbeginaligned\n\ttextmaxmin quad\n\tsum_z in mathcalZsum_r in mathcalR beta_zr^kP_zr\n\ttextst quad\n\tP_zr = sum_y in mathcalGsum_t in mathcalT omega_t Theta_ytzr \n\t f leq f^* + delta \n\tAx = b\nendaligned\n\nwhere, beta_zr is a random objective fucntion coefficient betwen 0100 for MGA iteration k. Theta_ytzr is a generation of technology y in zone z in time period t that belongs to a resource type r. We aggregate Theta_ytzr into a new variable P_zr that represents total generation from technology type r in a zone z. In the second constraint above, delta denote the increase in budget from the least-cost solution and f represents the expression for the total system cost. The constraint Ax = b represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#Multi-stage-specific-functions","page":"Public API","title":"Multi-stage specific functions","text":"","category":"section"},{"location":"Public_API/public_api/","page":"Public API","title":"Public API","text":"GenX.configure_multi_stage_inputs\nGenX.run_ddp\nGenX.write_multi_stage_outputs","category":"page"},{"location":"Public_API/public_api/#GenX.configure_multi_stage_inputs","page":"Public API","title":"GenX.configure_multi_stage_inputs","text":"function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)\n\nThis function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:\n\nOvernight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.\nAnnualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by \"StageLength\" field in multi_stage_settings.yml).\nInternal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.\nWhen NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the \"Line_Max_Flow_Possible_MW\" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.\n\ninputs:\n\ninputs_d - dict object containing model inputs dictionary generated by load_inputs().\nsettings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\nNetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the \"NetworkExpansion\" field in genx_settings.yml.\n\nreturns: dictionary containing updated model inputs, to be used in the generate_model() method.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.run_ddp","page":"Public API","title":"GenX.run_ddp","text":"run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)\n\nThis function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.\n\ninputs:\n\nmodels_d – Dictionary which contains a JuMP model for each model period.\nsetup - Dictionary object containing GenX settings and key parameters.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.\n\nreturns:\n\nmodels_d – Dictionary which contains a JuMP model for each model stage, modified by this method.\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.write_multi_stage_outputs","page":"Public API","title":"GenX.write_multi_stage_outputs","text":"write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)\n\nThis function calls various methods which write multi-stage modeling outputs as .csv files.\n\ninputs:\n\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Concept_Overview/power_balance/#Power-Balance","page":"Power Balance","title":"Power Balance","text":"","category":"section"},{"location":"Model_Concept_Overview/power_balance/","page":"Power Balance","title":"Power Balance","text":"The power balance constraint of the model ensures that electricity demand is met at every time step in each zone. As shown in the constraint, electricity demand, D_tz, at each time step and for each zone must be strictly equal to the sum of generation, Theta_yzt, from thermal technologies (mathcalH), curtailable variable renewable energy resources (mathcalVRE), must-run resources (mathcalMR), and hydro resources (mathcalW). At the same time, energy storage devices (mathcalO) can discharge energy, Theta_yzt to help satisfy demand, while when these devices are charging, Pi_yzt, they increase demand. Similarly, co-located variable renewable energy and storage resources (mathcalVS and mathcalVS^stor to represent co-located resources with a storage component) can generate electricity from the solar PV and/or wind component and discharge electricity from the storage resource, Theta_yzt to help satisfy demand, and charge from the grid, Pi_yzt, if the storage component of the resource exists. (For the case of flexible demand resources (mathcalDF), delaying demand, Pi_yzt, decreases demand while satisfying delayed demand, Theta_yzt, increases demand.) Price-responsive demand curtailment, Lambda_szt, also reduces demand. Finally, power flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign in the below constraint. At the same time losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see Transmission).","category":"page"},{"location":"Model_Concept_Overview/power_balance/","page":"Power Balance","title":"Power Balance","text":"beginaligned\n\tsum_yin mathcalHTheta_yzt +sum_yin mathcalVRETheta_yzt +sum_yin mathcalMRTheta_yzt + sum_yin mathcalO(Theta_yzt-Pi_yzt) + \n\t sum_yin mathcalDF(-Theta_yzt+Pi_yzt) +sum_yin mathcalWTheta_yzt+ sum_yin mathcalVSTheta_yzt - sum_yin mathcalVS^storPi_yzt + \n\t sum_sin mathcalSLambda_szt - sum_lin mathcalL(varphi^map_lz times Phi_lt) -frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot)) = D_zt\n\tquad quad forall zin mathcalZ t in mathcalT\nendaligned","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"\n","category":"page"},{"location":"#Welcome-to-the-GenX-documentation!","page":"GenX: Introduction","title":"Welcome to the GenX documentation!","text":"","category":"section"},{"location":"#What-is-GenX?","page":"GenX: Introduction","title":"What is GenX?","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX is a highly-configurable, open source electricity resource capacity expansion model that incorporates several state-of-the-art practices in electricity system planning to offer improved decision support for a changing electricity landscape.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The model was originally developed by Jesse D. Jenkins and Nestor A. Sepulveda at the Massachusetts Institute of Technology and is now jointly maintained by a team of contributors at the Princeton University ZERO Lab (led by Jenkins), MIT (led by Ruaridh MacDonald), and NYU (led by Dharik Mallapragada). ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX is a constrained linear or mixed integer linear optimization model that determines the portfolio of electricity generation, storage, transmission, and demand-side resource investments and operational decisions to meet electricity demand in one or more future planning years at lowest cost, while subject to a variety of power system operational constraints, resource availability limits, and other imposed environmental, market design, and policy constraints.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX features a modular and transparent code structure developed in Julia + JuMP. The model is designed to be highly flexible and configurable for use in a variety of applications from academic research and technology evaluation to public policy and regulatory analysis and resource planning. See the User Guide for more information on how to use GenX and the Developer Guide for more information on how to contribute to GenX.","category":"page"},{"location":"#Uses","page":"GenX: Introduction","title":"Uses","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.","category":"page"},{"location":"#Roadmap-of-the-Documentation:-A-Guide-for-the-Users-and-Developers","page":"GenX: Introduction","title":"Roadmap of the Documentation: A Guide for the Users and Developers","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"This section provides a quick guidance as to how to navigate through the different parts of the documentation pages; what the different sections contain, and how to relate it to the different parts of the GenX code-base. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"This page serves as a gentle introduction to what GenX is meant for and what it does. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The next subsection, Installation Guide goes over how to download and install GenX and also how to download and install the Julia programming language (in which GenX is written) and the different open-source non-commercial freely available solvers, as well as the commercial solvers and the respective JuMP interfaces. This subsection also goes over installing the environment dependencies and instantiating a virtual environment.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"We also mention the shortcomings of GenX and some third party extentions in the next couple subsections","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The next section is Getting Started goes over Running GenX and has two subsections. The first subsection, Example cases, gives a walkthrough through some predefined example systems and how to run GenX for those and interpret the results. It also tells how to run GenX for a user-defined case. The subsection Using commercial solvers: Gurobi or CPLEX talks specifically about how to run GenX with commercial solvers like Gurobi and CPLEX that are absolutely indispensable for solving large cases. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The third section, Tutorial starts with GenX Tutorials and gives a comprehensive tour of the different steps that are involved when a GenX capacity expansion simulation is run. It consists of 6 tutorial sections, each of which highlights the different important aspects of model construction and run of GenX. The different sections are configuring the GenX settings, visualizing the network, time domain reduction, generating the model, solving the model, and adjusting the different solver settings.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The User Guide, which the fourth section (User Guide) goes into the depths and details of the different steps and the settings and input parameters from the previous Tutorial section. The sections starts off with an overview of the workflow in GenX, briefing about the different steps (some of which we encountered in the Tutorials) of running GenX model. It then explains the different parameters of settings, policy, time-domain reduction, model structure, and output. Following this, the next subsection explains the different solver settings parameters of the different solvers. The next subsection goes over the different input CSV files and the different fields that are used there. The following two subsections are devoted to Time Domain Reduction (TDR). The first one walks through and explains the different settings parameters for TDR and the second one explains the couple different ways to run TDR for GenX and what exactly happens when we run TDR. The next four subsections, respectively, explains the different parameters, inputs, and outputs, and what happens when Modeling to Generate Alternatives (MGA), Multi-stage model, slack variables for policies (when we want to satisfy policy constraints in a soft manner by adding penalty of violation in the objective function), and Method of Morris. Finally, the last two sections are about the different steps involved while solving the model and the explanation of different output fields for both the default settings and user-specific settings. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The Model Concept and Overview section first introduces the GenX model in GenX Model Introduction and talks about its scope. It also introduces the notations, the objective function, and the power balance constraints. This is the first section which delves into the theoretical and mathematical details of the model, which is the most important one for model developers.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The Model Reference, which is the sixth section delves deep into the GenX model and introduces the mathematical formulation, while discussing the physical interpretations of all the different parts of the GenX model. This section starts off with discussing the Core of the model, which models the Discharge, Non-Served Energy, Operational Reserves, Transmission, Unit Commitment, CO2, and Fuel. The different parts of the model consists of the different tyoe of generating resources (thermal, hydro, VRE, storage etc.), transmission network (modeling of flows as well as losses), demand modeling, operating reserves, unit commitment, different policies (such as CO2 constraint, capacity reserve margin, energy share requirement, min and max cap requirement etc.). This section also mentions about the different Julia functions (or methods) used for loading the input files, building the model, solving it, and generating the output files. Also, this is the section that explains the internal details of the Julia functions used for TDR, MGA, Method of Morris, Multi-stage modeling, and the several utility functions used throughout the GenX code-base. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The seventh section, Public API Reference Public Documentation is for describing the functions that are directly accessible to an external program from GenX (like loading inputs, generating output, running TDR script etc.) and how an external \"client\" code can access the GenX features, if the user desires to run his/her own code instead of the Run.jl provided by us.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The eighth section, Third Party Extension Additional Third Party Extensions to GenX mentions about Pygenx, a Python interface for GenX, that was built by Daniel Olsen and GenX case runner for automated batch running, built by Jacob Schwartz.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"Finally, the ninth and last section, Developer Docs How to contribute to GenX talks about the resource organization in GenX, how to add a new user-defined resource, and also several JuMP functions that are used as utility throughout the GenX code-base. ","category":"page"},{"location":"#How-to-cite-GenX","page":"GenX: Introduction","title":"How to cite GenX","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"We recommend users of GenX to cite it in their academic publications and patent filings. Here's the text to put up as the citation for GenX: MIT Energy Initiative and Princeton University ZERO lab. [GenX](https://github.com/GenXProject/GenX): a configurable power system capacity expansion model for studying low-carbon energy futures n.d. https://github.com/GenXProject/GenX.","category":"page"},{"location":"#Acknowledgement","page":"GenX: Introduction","title":"Acknowledgement","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The GenX team expresses deep gratitude to Laura Zwanziger and Jacob Schwartz for designing the Julia-themed GenX logo and to Maya Mutic for developing the tutorials along with Filippo Pecci and Luca Bonaldo. ","category":"page"},{"location":"#License","page":"GenX: Introduction","title":"License","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX is released under the General Public License, GPL-2.0","category":"page"},{"location":"#Index","page":"GenX: Introduction","title":"Index","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"Pages = [\"Model_Reference/core.md\",\n \"Model_Reference/Resources/curtailable_variable_renewable.md\",\n \"Model_Reference/Resources/flexible_demand.md\",\n \"Model_Reference/Resources/hydro_res.md\",\n \"Model_Reference/Resources/hydro_inter_period_linkage.md\",\n \"Model_Reference/Resources/must_run.md\",\n \"Model_Reference/Resources/storage.md\",\n \"Model_Reference/Resources/investment_charge.md\",\n \"Model_Reference/Resources/investment_energy.md\",\n \"Model_Reference/Resources/long_duration_storage.md\",\n \"Model_Reference/Resources/storage_all.md\",\n \"Model_Reference/Resources/storage_asymmetric.md\",\n \"Model_Reference/Resources/storage_symmetric.md\",\n \"Model_Reference/Resources/vre_stor.md\",\n \"Model_Reference/Resources/thermal.md\",\n \"Model_Reference/Resources/thermal_commit.md\",\n \"Model_Reference/Resources/thermal_no_commit.md\",\n \"Model_Reference/Resources/electrolyzers.md\",\n \"Model_Reference/Resources/maintenance.md\",\n \"Model_Reference/policies.md\",\n \"User_Guide/solver_configuration.md\",\n \"Model_Reference/load_inputs.md\",\n \"Model_Reference/TDR.md\",\n \"Model_Reference/Multi_Stage/configure_multi_stage_inputs.md\",\n \"Model_Reference/Multi_Stage/dual_dynamic_programming.md\",\n \"Public_API/solve_model.md\",\n \"Public_API/mga.md\",\n \"Public_API/methodofmorris.md\",\n \"Public_API/write_outputs.md\"]","category":"page"},{"location":"Model_Reference/Resources/hydro_res/#Hydro-Resources","page":"Hydro Reservoir","title":"Hydro Resources","text":"","category":"section"},{"location":"Model_Reference/Resources/hydro_res/","page":"Hydro Reservoir","title":"Hydro Reservoir","text":"Modules = [GenX]\nPages = [\"hydro_res.jl\"]","category":"page"},{"location":"Model_Reference/Resources/hydro_res/#GenX.hydro_res!-Tuple{JuMP.Model, Dict, Dict}","page":"Hydro Reservoir","title":"GenX.hydro_res!","text":"hydro_res!(EP::Model, inputs::Dict, setup::Dict)\n\nThis module defines the operational constraints for reservoir hydropower plants. Hydroelectric generators with water storage reservoirs (y in mathcalW) are effectively modeled as energy storage devices that cannot charge from the grid and instead receive exogenous inflows to their storage reservoirs, reflecting stream flow inputs. For resources with unknown reservoir capacity (y in mathcalW^nocap), their operation is parametrized by their generation efficiency, eta_yz^down, and energy inflows to the reservoir at every time-step, represented as a fraction of the total power capacity,(rho^max_yzt). In case reservoir capacity is known (y in mathcalW^cap), an additional parameter, mu^stor_yz, referring to the ratio of energy capacity to discharge power capacity, is used to define the available reservoir storage capacity.\n\nStorage inventory balance Reservoir hydro systems are governed by the storage inventory balance constraint given below. This constraint enforces that energy level of the reservoir resource y and zone z in time step t (Gamma_yzt) is defined as the sum of the reservoir level in the previous time step, less the amount of electricity generated, Theta_yzt (accounting for the generation efficiency, eta_yz^down), minus any spillage varrho_yzt, plus the hourly inflows into the reservoir (equal to the installed reservoir discharged capacity times the normalized hourly inflow parameter rho^max_yz t).\n\nbeginaligned\nGamma_yzt = Gamma_yzt-1 -frac1eta_yz^downTheta_yzt - varrho_yzt + rho^max_yzt times Delta^total_yz hspace1 cm forall y in mathcalW z in mathcalZ t in mathcalT^interior \nGamma_yzt = Gamma_yzt+tau^period-1 -frac1eta_yz^downTheta_yzt - varrho_yzt + rho^max_yzt times Delta^total_yz hspace1 cm forall y in mathcalW z in mathcalZ t in mathcalT^start\nendaligned\n\nWe implement time-wrapping to endogenize the definition of the intial state prior to the first period with the following assumption. If time step t is the first time step of the year then storage inventory at t is defined based on last time step of the year. Alternatively, if time step t is the first time step of a representative period, then storage inventory at t is defined based on the last time step of the representative period. Thus, when using representative periods, the storage balance constraint for hydro resources does not allow for energy exchange between representative periods. Note: in future updates, an option to model hydro resources with large reservoirs that can transfer energy across sample periods will be implemented, similar to the functions for modeling long duration energy storage in long_duration_storage.jl.\n\nRamping Limits The following constraints enforce hourly changes in power output (ramps down and ramps up) to be less than the maximum ramp rates (kappa^down_yz and kappa^up_yz ) in per unit terms times the total installed capacity of technology y (Delta^total_yz).\n\nbeginaligned\nTheta_yzt + f_yzt + r_yzt - Theta_yzt-1 - f_yzt-1 leq kappa^up_yz times Delta^total_yz\nhspace2 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nbeginaligned\nTheta_yzt-1 + f_yzt-1 + r_yzt-1 - Theta_yzt - f_yztleq kappa^down_yz Delta^total_yz\nhspace2 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nRamping constraints are enforced for all time steps except the first time step of the year or first time of each representative period when using representative periods to model grid operations.\n\nPower generation and stream flow bounds Electricity production plus total spilled power from hydro resources is constrained to always be above a minimum output parameter, rho^min_yz, to represent operational constraints related to minimum stream flows or other demands for water from hydro reservoirs. Electricity production is constrained by either the the net installed capacity or by the energy level in the reservoir in the prior time step, whichever is more binding. For the latter constraint, the constraint for the first time step of the year (or the first time step of each representative period) is implemented based on energy storage level in last time step of the year (or last time step of each representative period).\n\nbeginaligned\nTheta_yzt + varrho_yzt geq rho^min_yz times Delta^total_yz\nhspace2 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nbeginaligned\nTheta_yt leq times Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ tin mathcalT\nendaligned\n\nbeginaligned\nTheta_yzt leq Gamma_yt-1\nhspace4 cm forall y in mathcalW z in mathcalZ tin mathcalT\nendaligned\n\nReservoir energy capacity constraint In case the reservoir capacity is known (y in W^cap), then an additional constraint enforces the total stored energy in each time step to be less than or equal to the available reservoir capacity. Here, the reservoir capacity is defined multiplying the parameter, mu^stor_yz with the available power capacity.\n\nbeginaligned\nGamma_yz t leq mu^stor_yztimes Delta^total_yz\nhspace4 cm forall y in mathcalW^cap z in mathcalZ tin mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/hydro_res/#GenX.hydro_res_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Hydro Reservoir","title":"GenX.hydro_res_operational_reserves!","text":"hydro_res_operational_reserves!(EP::Model, inputs::Dict)\n\nThis module defines the modified constraints and additional constraints needed when modeling operating reserves\n\nModifications when operating reserves are modeled When modeling operating reserves, the constraints regarding maximum power flow limits are modified to account for procuring some of the available capacity for frequency regulation (f_yzt) and \"updward\" operating (or spinning) reserves (r_yzt).\n\nbeginaligned\n Theta_yzt + f_yzt +r_yzt leq times Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ tin mathcalT\nendaligned\n\nThe amount of downward frequency regulation reserves cannot exceed the current power output.\n\nbeginaligned\n f_yzt leq Theta_yzt\nhspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nThe amount of frequency regulation and operating reserves procured in each time step is bounded by the user-specified fraction (upsilon^reg_yz,upsilon^rsv_yz) of nameplate capacity for each reserve type, reflecting the maximum ramp rate for the hydro resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nbeginaligned\nf_yzt leq upsilon^reg_yz times Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT \nr_yz t leq upsilon^rsv_yztimes Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/maintenance/#Optimized-Scheduled-Maintenance","page":"Scheduled maintenance for various resources","title":"Optimized Scheduled Maintenance","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Added in v0.4","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"In the real world, some types of resources (notably, fission) require regular scheduled maintenance, which often takes several weeks. During this time, the plant produces no power. This module allows GenX to find the best time of year for plants to undergo maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Scheduled maintenance is implemented only for thermal plants with unit commitment (THERM=1).","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Description-of-the-maintenance-model","page":"Scheduled maintenance for various resources","title":"Description of the maintenance model","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"A plant requires a single contiguous period of h ge 1 hours of maintenance, every y ge 1 years. For each plant, the best time to start the maintenance period is determined by the optimizer.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"During maintenance, the plant cannot be \"commited\", and therefore","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"uses no fuel,\nproduces no power,\nand does not contribute to reserves.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Additionally, ","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"the plant does not contribute to any Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Treatment-of-plants-that-require-maintenance-only-every-few-years","page":"Scheduled maintenance for various resources","title":"Treatment of plants that require maintenance only every few years","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"GenX models a long-term equilibrium, and each problem generally represents a single full year. If a plant requires maintenance every y years, we take the simplification that at least 1y of the plants must undergo maintenance in the modeled year.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"See also \"Interaction with integer unit commitment\" below.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Reduction-of-number-of-possible-start-dates","page":"Scheduled maintenance for various resources","title":"Reduction of number of possible start dates","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"This module creates constraints which work across long periods, and consequently can be very expensive to solve. In order to reduce the expense, the set of possible maintenance start dates can be limited. Rather than have maintenance potentially start every hour, one can have possible start dates which are once per day, once per week, etc. (In reality, maintenance is likely scheduled months in advance, so optimizing down to the hour may not be realistic anyway.)","category":"page"},{"location":"Model_Reference/Resources/maintenance/#How-to-use","page":"Scheduled maintenance for various resources","title":"How to use","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"There are four columns which need to be added to the plant data, i.e. in the resource .csv files:","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"MAINT should be 1 for plants that require maintenance and 0 otherwise.\nMaintenance_Duration is the number of hours the maintenance period lasts.\nMaintenance_Cycle_Length_Years. If 1, maintenance every year, if 3 maintenance every 3 years, etc.\nMaintenance_Begin_Cadence. Spacing between hours in which maintenance can start.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The last three fields must be integers which are greater than 0. They are ignored for any plants which do not require maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Maintenance_Duration must be less than the total number of hours in the year.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If Maintenance_Begin_Cadence is 1 then the maintenance can begin in any hour. If it is 168 then it can begin in hours 1, 169, 337, etc.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Restrictions-on-use","page":"Scheduled maintenance for various resources","title":"Restrictions on use","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The maintenance module has these restrictions:","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"More than a single maintenance period per year (i.e. every three months) is not possible in the current formulation.\nOnly full-year cases can be run; there must be only one \"representative period\".","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"It would not make sense to model a month-long maintenance period when the year is modeled as a series of representative weeks, for example.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Interaction-with-integer-unit-commitment","page":"Scheduled maintenance for various resources","title":"Interaction with integer unit commitment","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If integer unit commitment is on (UCommit=1) this module may not produce correct results; there may be more maintenance than the user wants. This is because the formulation specifies that the number of plants that go down for maintenance in the simulated year must be at least (the number of plants in the zone)/(the maintenance cycle length in years). As a reminder, the number of plants is eTotalCap / Cap_Size.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If there were three 500 MW plants (total 1500 MW) in a zone, and they require maintenance every three years (Maintenance_Cycle_Length_Years=3), the formulation will work properly: one of the three plants will go under maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"But if there was only one 500 MW plant, and it requires maintenance every 3 years, the constraint will still make it do maintenance every year, because ceil(1/3) is 1. The whole 500 MW plant will do maintenance. This is the unexpected behavior.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"However, if integer unit commitment was relaxed to \"linearized\" unit commitment (UCommit=2), the model will have only 500 MW / 3 = 166.6 MW worth of this plant do maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Hint:-pre-scheduling-maintenance","page":"Scheduled maintenance for various resources","title":"Hint: pre-scheduling maintenance","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If you want to pre-schedule when maintenance occurs, you might not need this module. Instead, you could set the maximum power output of the plant to zero for a certain period, or make its fuel extremely expensive during that time. However, the plant would still be able to contribute to the Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Outputs-produced","page":"Scheduled maintenance for various resources","title":"Outputs produced","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If at least one plant has MAINT=1, a file maint_down.csv will be written listing how many plants are down for maintenance in each timestep.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Notes-on-mathematical-formulation","page":"Scheduled maintenance for various resources","title":"Notes on mathematical formulation","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The formulation of the maintenance state is very similar to the formulation of unit commitment.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"There is a variable called something like vMSHUT which is analogous to vSTART and controls the start of the maintenance period. There is another variable called something like vMDOWN analogous to vCOMMIT which controls the maintenance status in any hour.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"A constraint ensures that the value of vMDOWN in any hour is always more than the number of vMSHUTs in the previous Maintenance_Duration hours.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Another constraint ensures that the number of plants committed (vCOMMIT) at any one time plus the number of plants under maintenance (vMDOWN) is less than the total number of plants.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Developer-note:-adding-maintenance-to-a-resource","page":"Scheduled maintenance for various resources","title":"Developer note: adding maintenance to a resource","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The maintenance formulation is applied on a per-resource basis, by calling the function maintenance_formulation!.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"GenX.maintenance_formulation!\nGenX.resources_with_maintenance\nGenX.maintenance_down_name\nGenX.maintenance_shut_name\nGenX.controlling_maintenance_start_hours\nGenX.ensure_maintenance_variable_records!\nGenX.has_maintenance\nGenX.maintenance_down_variables","category":"page"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_formulation!","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_formulation!","text":"maintenance_formulation!(EP::Model,\n inputs::Dict,\n resource_component::AbstractString,\n r_id::Int,\n maint_begin_cadence::Int,\n maint_dur::Int,\n maint_freq_years::Int,\n cap::Float64,\n vcommit::Symbol,\n ecap::Symbol,\n integer_operational_unit_commitment::Bool)\n\nEP: the JuMP model\ninputs: main data storage\nresource_component: unique resource name with optional component name\n If the plant has more than one component, this could identify a specific part which\n is undergoing maintenance.\nr_id: Resource ID (unique resource integer)\nmaint_begin_cadence:\n It may be too expensive (from an optimization perspective) to allow maintenance\n to begin at any time step during the simulation. Instead this integer describes\n the cadence of timesteps in which maintenance can begin. Must be at least 1.\nmaint_dur: Number of timesteps that maintenance takes. Must be at least 1.\nmaint_freq_years: 1 is maintenannce every year,\n 2 is maintenance every other year, etc. Must be at least 1.\ncap: Plant electrical capacity.\nvcommit: Symbol of vCOMMIT-like variable.\necap: Symbol of eTotalCap-like variable.\ninteger_operational_unit_commitment: whether this plant has integer unit\n commitment for operational variables.\n\nCreates maintenance-tracking variables and adds their Symbols to two Sets in `inputs`.\nAdds constraints which act on the vCOMMIT-like variable.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.resources_with_maintenance","page":"Scheduled maintenance for various resources","title":"GenX.resources_with_maintenance","text":"resources_with_maintenance(df::DataFrame)::Vector{Int}\n\nGet a vector of the R_ID's of all resources listed in a dataframe\nthat have maintenance requirements. If there are none, return an empty vector.\n\nThis method takes a specific dataframe because compound resources may have their\ndata in multiple dataframes.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_down_name","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_down_name","text":"maintenance_down_name(resource_component::AbstractString)::String\n\nJuMP variable name to control whether a resource-component is down for maintenance.\nHere resource-component could be a whole resource or a component (for complex resources).\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_shut_name","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_shut_name","text":"maintenance_shut_name(resource_component::AbstractString)::String\n\nJuMP variable name to control when a resource-components begins maintenance.\nHere resource-component could be a whole resource or a component (for complex resources).\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.controlling_maintenance_start_hours","page":"Scheduled maintenance for various resources","title":"GenX.controlling_maintenance_start_hours","text":"controlling_maintenance_start_hours(p::Int, t::Int, maintenance_duration::Int, maintenance_begin_hours::UnitRange{Int64})\n\np: hours_per_subperiod\nt: the current hour\nmaintenance_duration: length of a maintenance period\nmaintenance_begin_hours: collection of hours in which maintenance is allowed to start\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.ensure_maintenance_variable_records!","page":"Scheduled maintenance for various resources","title":"GenX.ensure_maintenance_variable_records!","text":"ensure_maintenance_variable_records!(dict::Dict)\n\ndict: a dictionary of model data\n\nThis should be called by each method that adds maintenance formulations,\nto ensure that certain entries in the model data dict exist.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.has_maintenance","page":"Scheduled maintenance for various resources","title":"GenX.has_maintenance","text":"has_maintenance(dict::Dict)\n\ndict: a dictionary of model data\n\nChecks whether the dictionary contains listings of maintenance-related variable names.\nThis is true only after `maintenance_formulation!` has been called.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_down_variables","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_down_variables","text":"maintenance_down_variables(dict::Dict)\n\ndict: a dictionary of model data\n\nget listings of maintenance-related variable names.\nThis is available only after `maintenance_formulation!` has been called.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/#Endogenous-Retirement","page":"Endogenous Retirement","title":"Endogenous Retirement","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/","page":"Endogenous Retirement","title":"Endogenous Retirement","text":"Modules = [GenX]\nPages = [\"endogenous_retirement.jl\"]","category":"page"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/#GenX.endogenous_retirement_discharge!-Tuple{JuMP.Model, Dict, Int64, Int64, Vector{Int64}}","page":"Endogenous Retirement","title":"GenX.endogenous_retirement_discharge!","text":"endogenous_retirement_discharge!(EP::Model, inputs::Dict, num_stages::Int, cur_stage::Int, stage_lens::Array{Int, 1})\n\nThis function models the following constraint\n\nbeginaligned\n RETCAP_yp geq sum^p_t=1 MINRET_yt + sum^r_t=1CAP_yt - sum^p_t=1RETCAP_yp\nendaligned\n\nwhere r in 1 (p-1) is defined as the last stage such that if we built y at the end of stage r, it would reach its end of life before the end of stage p. In other words, it is the largest index r in 1 (p-1) such that:\n\nbeginaligned\nsum^p_t=r+1StageLength_t leq LifeTime_y\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/#GenX.get_retirement_stage-Tuple{Int64, Int64, Vector{Int64}}","page":"Endogenous Retirement","title":"GenX.get_retirement_stage","text":"get_retirement_stage(cur_stage::Int, stage_len::Int, lifetime::Int, stage_lens::Array{Int, 1})\n\nThis function determines the model stage before which all newly built capacity must be retired. Used to enforce endogenous lifetime retirements in multi-stage modeling.\n\ninputs:\n\ncur_stage – An Int representing the current model stage p.\nlifetime – An Int representing the lifetime of a particular resource.\nstage_lens – An Int array representing the length L of each model stage.\n\nreturns: An Int representing the model stage in before which the resource must retire due to endogenous lifetime retirements.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#Utility-Functions","page":"Utility Functions","title":"Utility Functions","text":"","category":"section"},{"location":"Model_Reference/utility_functions/","page":"Utility Functions","title":"Utility Functions","text":"Modules = [GenX]\nPages = [\"utility.jl\"]","category":"page"},{"location":"Model_Reference/utility_functions/#GenX.by_rid_res-Tuple{Integer, Symbol, Vector{var\"#s267\"} where var\"#s267\"<:GenX.AbstractResource}","page":"Utility Functions","title":"GenX.by_rid_res","text":"by_rid_res(rid::Integer, sym::Symbol, rs::Vector{<:AbstractResource})\n\nThis function returns the value of the attribute `sym` for the resource given by the ID `rid`.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursafter-Tuple{Int64, Int64, Int64}","page":"Utility Functions","title":"GenX.hoursafter","text":"hoursafter(p::Int, t::Int, a::Int)\n\nDetermines the time index a hours after index t in a landscape starting from t=1 which is separated into distinct periods of length p.\n\nFor example, if p = 10, 1 hour after t=9 is t=10, 1 hour after t=10 is t=1, 1 hour after t=11 is t=2\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursafter-Tuple{Int64, Int64, UnitRange{Int64}}","page":"Utility Functions","title":"GenX.hoursafter","text":"hoursafter(p::Int, t::Int, b::UnitRange)\n\nThis is a generalization of hoursafter(... b::Int) to allow for example a=1:3 to fetch a Vector{Int} of the three hours after time index t.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursbefore-Tuple{Int64, Int64, Int64}","page":"Utility Functions","title":"GenX.hoursbefore","text":"hoursbefore(p::Int, t::Int, b::Int)\n\nDetermines the time index b hours before index t in a landscape starting from t=1 which is separated into distinct periods of length p.\n\nFor example, if p = 10, 1 hour before t=1 is t=10, 1 hour before t=10 is t=9 1 hour before t=11 is t=20\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursbefore-Tuple{Int64, Int64, UnitRange{Int64}}","page":"Utility Functions","title":"GenX.hoursbefore","text":"hoursbefore(p::Int, t::Int, b::UnitRange)\n\nThis is a generalization of hoursbefore(... b::Int) to allow for example b=1:3 to fetch a Vector{Int} of the three hours before time index t.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.is_nonzero-Tuple{DataFrames.DataFrame, Symbol}","page":"Utility Functions","title":"GenX.is_nonzero","text":"is_nonzero(df::DataFrame, col::Symbol)::BitVector\n\nThis function checks if a column in a dataframe is all zeros.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#Time-Domain-Reduction-(TDR)","page":"Time-domain Reduction","title":"Time Domain Reduction (TDR)","text":"","category":"section"},{"location":"Model_Reference/TDR/","page":"Time-domain Reduction","title":"Time-domain Reduction","text":"Modules = [GenX]\nPages = [\"time_domain_reduction.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"Model_Reference/TDR/#GenX.RemoveConstCols","page":"Time-domain Reduction","title":"GenX.RemoveConstCols","text":"RemoveConstCols(all_profiles, all_col_names)\n\nRemove and store the columns that do not vary during the period.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.check_condition-NTuple{5, Any}","page":"Time-domain Reduction","title":"GenX.check_condition","text":"check_condition(Threshold, R, OldColNames, ScalingMethod, TimestepsPerRepPeriod)\n\nCheck whether the greatest Euclidean deviation in the input data and the clustered representation is within a given proportion of the \"maximum\" possible deviation.\n\n(1 for Normalization covers 100%, 4 for Standardization covers ~95%)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.cluster","page":"Time-domain Reduction","title":"GenX.cluster","text":"cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false, random=true)\n\nGet representative periods using cluster centers from kmeans or kmedoids.\n\nK-Means: https://juliastats.org/Clustering.jl/dev/kmeans.html\n\nK-Medoids: https://juliastats.org/Clustering.jl/stable/kmedoids.html\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.cluster_inputs","page":"Time-domain Reduction","title":"GenX.cluster_inputs","text":"cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false; random=true)\n\nUse kmeans or kmedoids to cluster raw demand profiles and resource capacity factor profiles into representative periods. Use Extreme Periods to capture noteworthy periods or periods with notably poor fits.\n\nIn Demand_data.csv, include the following:\n\nTimesteps_per_Rep_Period - Typically 168 timesteps (e.g., hours) per period, this designates the length of each representative period.\nUseExtremePeriods - Either 1 or 0, this designates whether or not to include outliers (by performance or demand/resource extreme) as their own representative periods. This setting automatically includes the periods with maximum demand, minimum solar cf and minimum wind cf as extreme periods.\nClusterMethod - Either 'kmeans' or 'kmedoids', this designates the method used to cluster periods and determine each point's representative period.\nScalingMethod - Either 'N' or 'S', this designates directs the module to normalize ([0,1]) or standardize (mean 0, variance 1) the input data.\nMinPeriods - The minimum number of periods used to represent the input data. If using UseExtremePeriods, this must be at least three. If IterativelyAddPeriods if off, this will be the total number of periods.\nMaxPeriods - The maximum number of periods - both clustered periods and extreme periods - that may be used to represent the input data.\nIterativelyAddPeriods - Either 1 or 0, this designates whether or not to add periods until the error threshold between input data and represented data is met or the maximum number of periods is reached.\nThreshold - Iterative period addition will end if the period farthest (Euclidean Distance) from its representative period is within this percentage of the total possible error (for normalization) or ~95% of the total possible error (for standardization). E.g., for a threshold of 0.01, every period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the max number of periods is reached).\nIterateMethod - Either 'cluster' or 'extreme', this designates whether to add clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.\nnReps - The number of times to repeat each kmeans/kmedoids clustering at the same setting.\nDemandWeight - Default 1, this is an optional multiplier on demand columns in order to prioritize better fits for demand profiles over resource capacity factor profiles.\nWeightTotal - Default 8760, the sum to which the relative weights of representative periods will be scaled.\nClusterFuelPrices - Either 1 or 0, this indicates whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data_clustered.csv with reshaped fuel prices based on the number and size of the representative weeks, assuming a constant time series of fuel prices with length equal to the number of timesteps in the raw input data.\nMultiStageConcatenate - (Only considered if MultiStage = 1 in genx_settings.yml) If 1, this designates that the model should time domain reduce the input data of all model stages together. Else if 0, [still in development] the model will time domain reduce only the first stage and will apply the periods of each other model stage to this set of representative periods by closest Eucliden distance.\n\nFor co-located VRE-STOR resources, all capacity factors must be in the Generatorsvariability.csv file in addition to separate Vreandstorsolarvariability.csv and Vreandstorwind_variability.csv files. The co-located solar PV and wind profiles for co-located resources will be separated into different CSV files to be read by loading the inputs after the clustering of the inputs has occurred. \n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.get_absolute_extreme-NTuple{4, Any}","page":"Time-domain Reduction","title":"GenX.get_absolute_extreme","text":"get_absolute_extreme(DF, statKey, col_names, ConstCols)\n\nGet the period index of the single timestep with the minimum or maximum demand or capacity factor.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.get_demand_multipliers","page":"Time-domain Reduction","title":"GenX.get_demand_multipliers","text":"get_demand_multipliers(ClusterOutputData, ModifiedData, M, W, DemandCols, TimestepsPerRepPeriod, NewColNames, NClusters, Ncols)\n\nGet multipliers to linearly scale clustered demand profiles L zone-wise such that their weighted sum equals the original zonal total demand. Scale demand profiles later using these multipliers in order to ensure that a copy of the original demand is kept for validation.\n\nFind k_z such that:\n\nsum_i in I L_iz = sum_t in T m in M C_tmz cdot fracw_mT cdot k_z forall z in Z\n\nwhere Z is the set of zones, I is the full time domain, T is the length of one period (e.g., 168 for one week in hours), M is the set of representative periods, L_iz is the original zonal demand profile over time (hour) index i, C_imz is the demand in timestep i for representative period m in zone z, w_m is the weight of the representative period equal to the total number of hours that one hour in representative period m represents in the original profile, and k_z is the zonal demand multiplier returned by the function.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.get_extreme_period","page":"Time-domain Reduction","title":"GenX.get_extreme_period","text":"get_extreme_period(DF, GDF, profKey, typeKey, statKey,\n ConstCols, demand_col_names, solar_col_names, wind_col_names)\n\nIdentify extreme week by specification of profile type (Demand, PV, Wind), measurement type (absolute (timestep with min/max value) vs. integral (period with min/max summed value)), and statistic (minimum or maximum). I.e., the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select \"Demand\", \"System, \"Absolute, and \"Max\".\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.get_integral_extreme-NTuple{4, Any}","page":"Time-domain Reduction","title":"GenX.get_integral_extreme","text":"get_integral_extreme(GDF, statKey, col_names, ConstCols)\n\nGet the period index with the minimum or maximum demand or capacity factor summed over the period.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.get_worst_period_idx-Tuple{Any}","page":"Time-domain Reduction","title":"GenX.get_worst_period_idx","text":"get_worst_period_idx(R)\n\nGet the index of the period that is farthest from its representative period by Euclidean distance.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.parse_data-Tuple{Any}","page":"Time-domain Reduction","title":"GenX.parse_data","text":"parse_data(myinputs)\n\nGet demand, solar, wind, and other curves from the input data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.parse_multi_stage_data-Tuple{Any}","page":"Time-domain Reduction","title":"GenX.parse_multi_stage_data","text":"parse_mutli_period_data(inputs_dict)\n\nGet demand, solar, wind, and other curves from multi-stage input data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.rmse_score-Tuple{Any, Any}","page":"Time-domain Reduction","title":"GenX.rmse_score","text":"rmse_score(y_true, y_pred)\n\nCalculates Root Mean Square Error.\n\nRMSE = sqrtfrac1nSigma_i=1^nBig(fracd_i -f_isigma_iBig)^2\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.scale_weights","page":"Time-domain Reduction","title":"GenX.scale_weights","text":"scale_weights(W, H)\n\nLinearly scale weights W such that they sum to the desired number of timesteps (hours) H.\n\nw_j leftarrow H cdot fracw_jsum_i w_i forall w_j in W\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/","page":"Time-domain Reduction","title":"Time-domain Reduction","text":"GenX.run_timedomainreduction!","category":"page"},{"location":"Model_Reference/TDR/#GenX.run_timedomainreduction!","page":"Time-domain Reduction","title":"GenX.run_timedomainreduction!","text":"Run the GenX time domain reduction on the given case folder\n\ncase - folder for the case stage_id - possibly something to do with MultiStage verbose - print extra outputs\n\nThis function overwrites the time-domain-reduced inputs if they already exist.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/flexible_demand/#Flexible-Demand","page":"Flexible Demand","title":"Flexible Demand","text":"","category":"section"},{"location":"Model_Reference/Resources/flexible_demand/","page":"Flexible Demand","title":"Flexible Demand","text":"Modules = [GenX]\nPages = [\"flexible_demand.jl\"]","category":"page"},{"location":"Model_Reference/Resources/flexible_demand/#GenX.flexible_demand!-Tuple{JuMP.Model, Dict, Dict}","page":"Flexible Demand","title":"GenX.flexible_demand!","text":"flexible_demand!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the operating constraints for flexible demand resources. As implemented, flexible demand resources (y in mathcalDF) are characterized by: a) maximum deferrable demand as a fraction of available capacity in a particular time step t, rho^max_yzt, b) the maximum time this demand can be advanced and delayed, defined by parameters, tau^advance_yz and tau^delay_yz, respectively and c) the energy losses associated with shifting demand, eta_yz^dflex.\n\nTracking total deferred demand The operational constraints governing flexible demand resources are as follows. The first two constraints model keep track of inventory of deferred demand in each time step. Specifically, the amount of deferred demand remaining to be served (Gamma_yzt) depends on the amount in the previous time step minus the served demand during time step t (Theta_yzt) while accounting for energy losses associated with demand flexibility, plus the demand that has been deferred during the current time step (Pi_yzt). Note that variable Gamma_yzt in mathbbR, forall y in mathcalDF t in mathcalT. Similar to hydro inventory or storage state of charge constraints, for the first time step of the year (or each representative period), we define the deferred demand level based on level of deferred demand in the last time step of the year (or each representative period).\n\nbeginaligned\nGamma_yzt = Gamma_yzt-1 -eta_yz^dflexTheta_yzt +Pi_yzt hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT^interior \nGamma_yzt = Gamma_yzt +tau^period-1 -eta_yz^dflexTheta_yzt +Pi_yzt hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT^start\nendaligned\n\nBounds on available demand flexibility At any given time step, the amount of demand that can be shifted or deferred cannot exceed the maximum deferrable demand, defined by product of the availability factor (rho^max_yt) times the available capacity(Delta^total_yz).\n\nbeginaligned\nPi_yt leq rho^max_yztDelta_yz hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT\nendaligned\n\nMaximum time delay and advancements Delayed demand must then be served within a fixed number of time steps. This is done by enforcing the sum of demand satisfied (Theta_yzt) in the following tau^delay_yz time steps (e.g., t + 1 to t + tau^delay_yz) to be greater than or equal to the level of energy deferred during time step t.\n\nbeginaligned\nsum_e=t+1^t+tau^delay_yzTheta_yze geq Gamma_yzt\n hspace4 cm forall y in mathcalDFz in mathcalZ t in mathcalT\nendaligned\n\nA similar constraints maximum time steps of demand advancement. This is done by enforcing the sum of demand deferred (Pi_yt) in the following tau^advance_y time steps (e.g., t + 1 to t + tau^advance_y) to be greater than or equal to the total level of energy deferred during time t (-Gamma_yt). The negative sign is included to account for the established sign convention that treat demand deferred in advance of the actual demand is defined to be negative.\n\nbeginaligned\nsum_e=t+1^t+tau^advance_yzPi_yze geq -Gamma_yzt\n hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT\nendaligned\n\nIf t is first time step of the year (or the first time step of the representative period), then the above two constraints are implemented to look back over the last n time steps, starting with the last time step of the year (or the last time step of the representative period). This time-wrapping implementation is similar to the time-wrapping implementations used for defining the storage balance constraints for hydropower reservoir resources and energy storage resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Concept_Overview/objective_function/#Objective-Function","page":"Objective Function","title":"Objective Function","text":"","category":"section"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The objective function of GenX minimizes total annual electricity system costs over the following components shown in the below equation:","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"beginaligned\n textmin quad\n sum_y in mathcalG sum_z in mathcalZ left((pi^INVEST_yz times overlineOmega^size_yz times Omega_yz) + (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right) + \n sum_y in mathcalO sum_z in mathcalZ left( (pi^INVESTenergy_yz times Omega^energy_yz) + (pi^FOMenergy_yz times Delta^totalenergy_yz)right) + \n sum_y in mathcalO^asym sum_z in mathcalZ left( (pi^INVESTcharge_yz times Omega^charge_yz) + (pi^FOMcharge_yz times Delta^totalcharge_yz)right) + \n sum_y in mathcalG sum_z in mathcalZ sum_t in mathcalT left( omega_ttimes(pi^VOM_yz + pi^FUEL_yz)times Theta_yztright) + sum_y in mathcalO cup DF sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMcharge_yz times Pi_yztright) + \n sum_s in mathcalS sum_z in mathcalZ sum_t in mathcalT left(omega_t times n_s^slope times Lambda_sztright) + sum_t in mathcalT left(omega_t times pi^unmet_rsv times r^unmet_tright) \n sum_y in mathcalH sum_z in mathcalZ sum_t in mathcalTleft(omega_t times pi^START_yz times chi_sztright) + \n sum_l in mathcalLleft(pi^TCAP_l times bigtriangleupvarphi^max_lright) + \n sum_y in mathcalVS^inv sum_z in mathcalZ left( (pi^INVEST inv_yz times Omega^inv_yz)\n + (pi^FOM inv_yz times Delta^totalinv_yz)right) + \n sum_y in mathcalVS^pv sum_z in mathcalZ left( (pi^INVEST pv_yz times Omega^pv_yz)\n + (pi^FOM pv_yz times Delta^totalpv_yz)right) + \n sum_y in mathcalVS^wind sum_z in mathcalZ left( (pi^INVEST wind_yz times Omega^pv_yz)\n + (pi^FOM wind_yz times Delta^totalwind_yz)right) + \n sum_y in mathcalVS^asymdcdis sum_z in mathcalZ left( (pi^INVESTdcdis_yz times Omega^dcdis_yz)\n + (pi^FOMdcdis_yz times Delta^totaldcdis_yz)right) + \n sum_y in mathcalVS^asymdccha sum_z in mathcalZ left( (pi^INVESTdccha_yz times Omega^dccha_yz)\n + (pi^FOMdccha_yz times Delta^totaldccha_yz)right) + \n sum_y in mathcalVS^asymacdis sum_z in mathcalZ left( (pi^INVESTacdis_yz times Omega^acdis_yz)\n + (pi^FOMacdis_yz times Delta^totalacdis_yz)right) + \n sum_y in mathcalVS^asymaccha sum_z in mathcalZ left( (pi^INVESTaccha_yz times Omega^accha_yz)\n + (pi^FOMaccha_yz times Delta^totalaccha_yz)right) + \n sum_y in mathcalVS^pv sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMpv_yztimes eta^inverter_yz times Theta^pv_yztright) + \n sum_y in mathcalVS^wind sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMwind_yz times Theta^wind_yztright) + \n sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMdcdis_yz timeseta^inverter_yz times Theta^dc_yztright) + \n sum_y in mathcalVS^symdc cup mathcalVS^asymdccha sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMdccha_yz times fracPi^dc_yzteta^inverter_yzright) + \n sum_y in mathcalVS^symac cup mathcalVS^asymacdis sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMacdis_yz times Theta^ac_yztright) + \n sum_y in mathcalVS^symac cup mathcalVS^asymaccha sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMaccha_yz times Pi^ac_yztright) \nendaligned","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The first summation represents the fixed costs of generation/discharge over all zones and technologies, which reflects the sum of the annualized capital cost, pi^INVEST_yz, times the total new capacity added (if any), plus the Fixed O&M cost, pi^FOM_yz, times the net installed generation capacity, overlineOmega^size_yz times Delta^total_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources (y in mathcalO cup mathcalVS^stor). This term includes the sum of the annualized energy capital cost, pi^INVESTenergy_yz, times the total new energy capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed energy storage capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components (y in mathcalO^asym). This term includes the sum of the annualized charging power capital cost, pi^INVESTcharge_yz, times the total new charging power capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed charging power capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The fourth and fifth summations correspond to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, pi^FUEL_yz (if any), plus variable O&M cost, pi^VOM_yz times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, yinmathcalDF) in time step t, Theta_yzt, and the weight of each time step t, omega_t. The fifth summation represents the variable charging O&M cost, pi^VOMcharge_yz times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step t , Pi_yzt and the annual weight of time step t,omega_t. The weight of each time step, omega_t, is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, t such that the sum of omega_t forall t in T = 8760, approximating annual operating costs.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The sixth summation represents the total cost of unserved demand across all segments s of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), n_s^slope, times the amount of non-served energy, Lambda_yzt, for each segment on each zone during each time step (weighted by omega_t).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The seventh summation represents the total cost of not meeting hourly operating reserve requirements (if modeled), where pi^unmet_rsv is the cost penalty per unit of non-served reserve requirement, and r^unmet_t is the amount of non-served reserve requirement in each time step (weighted by omega_t).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. y in mathcalUC), equal to the cost of start-up, pi^START_yz, times the number of startup events, chi_yzt, for the cluster of units in each zone and time step (weighted by omega_t).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The ninth term corresponds to the transmission reinforcement or construction costs, for each transmission line (if modeled). Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, pi^TCAP_l, times the additional transmission capacity variable, bigtriangleupvarphi^max_l. Note that fixed O&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The tenth term onwards specifically relates to the breakdown investment, fixed O&M, and variable O&M costs associated with each configurable component of a co-located VRE and storage resource. The tenth term represents to the fixed cost of installed inverter capacity and is summed over only the co-located resources with an inverter component (y in mathcalVS^inv). This term includes the sum of the annualized inverter capital cost, pi^INVESTinv_yz, times the total new inverter capacity added (if any), plus the Fixed O&M cost, pi^FOM inv_yz, times the net installed inverter capacity, Delta^totalinv_yz (e.g., existing capacity less retirements plus additions). The eleventh term represents the fixed cost of installed solar PV capacity and is summed over only the co-located resources with a solar PV component (y in mathcalVS^pv). This term includes the sum of the annualized solar PV capital cost, pi^INVESTpv_yz, times the total new solar PV capacity added (if any), plus the Fixed O&M cost, pi^FOM pv_yz, times the net installed solar PV capacity, Delta^totalpv_yz (e.g., existing capacity less retirements plus additions). The twelveth term represents the fixed cost of installed wind capacity and is summed over only the co-located resources with a wind component (y in mathcalVS^wind). This term includes the sum of the annualized wind capital cost, pi^INVESTwind_yz, times the total new wind capacity added (if any), plus the Fixed O&M cost, pi^FOM wind_yz, times the net installed wind capacity, Delta^totalwind_yz (e.g., existing capacity less retirements plus additions). The thirteenth term represents the fixed cost of installed storage DC discharge capacity and is summed over only the co-located resources with an asymmetric storage DC discharge component (y in mathcalVS^asymdcdis). This term includes the sum of the annualized storage DC discharge capital cost, pi^INVESTdcdis_yz, times the total new storage DC discharge capacity added (if any), plus the Fixed O&M cost, pi^FOM dc dis_yz, times the net installed storage DC discharge capacity, Delta^totaldcdis_yz (e.g., existing capacity less retirements plus additions). The fourteenth term represents the fixed cost of installed storage DC charge capacity and is summed over only the co-located resources with an asymmetric storage DC charge component (y in mathcalVS^asymdccha). This term includes the sum of the annualized storage DC charge capital cost, pi^INVESTdccha_yz, times the total new storage DC charge capacity added (if any), plus the Fixed O&M cost, pi^FOM dc cha_yz, times the net installed storage DC charge capacity, Delta^totaldccha_yz (e.g., existing capacity less retirements plus additions). The fifteenth term represents the fixed cost of installed storage AC discharge capacity and is summed over only the co-located resources with an asymmetric storage AC discharge component (y in mathcalVS^asymacdis). This term includes the sum of the annualized storage AC discharge capital cost, pi^INVESTacdis_yz, times the total new storage AC discharge capacity added (if any), plus the Fixed O&M cost, pi^FOM ac dis_yz, times the net installed storage AC discharge capacity, Delta^totalacdis_yz (e.g., existing capacity less retirements plus additions). The sixteenth term represents to the fixed cost of installed storage AC charge capacity and is summed over only the co-located resources with an asymmetric storage AC charge component (y in mathcalVS^asymaccha). This term includes the sum of the annualized storage AC charge capital cost, pi^INVESTaccha_yz, times the total new storage AC charge capacity added (if any), plus the Fixed O&M cost, pi^FOM ac cha_yz, times the net installed storage AC charge capacity, Delta^totalaccha_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The seventeeth term onwards corresponds to the operational cost across all zones, technologies, and time steps for co-located VRE and storage resources. The seventeenth summation represents the variable O&M cost, pi^VOMpv_yz, times the energy generation by solar PV resources (yinmathcalVS^pv) in time step t, Theta^pv_yzt, the inverter efficiency, eta^inverter_yz, and the weight of each time step t, omega_t. The eighteenth summation represents the variable O&M cost, pi^VOMwind_yz, times the energy generation by wind resources (yinmathcalVS^wind) in time step t, Theta^wind_yzt, and the weight of each time step t, omega_t. The nineteenth summation represents the variable O&M cost, pi^VOMdcdis_yz, times the energy discharge by storage DC components (yinmathcalVS^symdc cup mathcalVS^asymdcdis) in time step t, Theta^dc_yzt, the inverter efficiency, eta^inverter_yz, and the weight of each time step t, omega_t. The twentieth summation represents the variable O&M cost, pi^VOMdccha_yz, times the energy withdrawn by storage DC components (yinmathcalVS^symdc cup mathcalVS^asymdccha) in time step t, Pi^dc_yzt, and the weight of each time step t, omega_t, and divided by the inverter efficiency, eta^inverter_yz. The twenty-first summation represents the variable O&M cost, pi^VOMacdis_yz, times the energy discharge by storage AC components (yinmathcalVS^symac cup mathcalVS^asymacdis) in time step t, Theta^ac_yzt, and the weight of each time step t, omega_t. The twenty-second summation represents the variable O&M cost, pi^VOMaccha_yz, times the energy withdrawn by storage AC components (yinmathcalVS^symac cup mathcalVS^asymaccha) in time step t, Pi^ac_yzt, and the weight of each time step t, omega_t. ","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"In summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions:","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"where and how to invest on capacity,\nhow to dispatch or operate that capacity,\nwhich consumer demand segments to serve or curtail,\nhow to cycle and commit thermal units subject to unit commitment decisions,\nand where and how to invest in additional transmission network capacity to increase power transfer capacity between zones.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"While the objective function is formulated as a cost minimization problem, it is also equivalent to a social welfare maximization problem, with the bulk of demand treated as inelastic and always served, and the utility of consumption for price-elastic consumers represented as a segment-wise approximation, as per the cost of unserved demand summation above.","category":"page"},{"location":"User_Guide/workflow/#User-Guide","page":"Overall workflow","title":"User Guide","text":"","category":"section"},{"location":"User_Guide/workflow/#Introduction","page":"Overall workflow","title":"Introduction","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"GenX is a constrained linear or mixed integer linear optimization model that determines the portfolio of electricity generation, storage, transmission, and demand-side resource investments and operational decisions to meet electricity demand in one or more future planning years at lowest cost, while subject to a variety of power system operational constraints, resource availability limits, and other imposed environmental, market design, and policy constraints.","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Depending on the planning problem or question to be studied, GenX can be configured with varying levels of model resolution and scope, with regards to: ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Temporal resolution of time series data such as electricity demand and renewable energy availability; \nPower system operational detail and unit commitment constraints; \nGeospatial resolution and transmission network representation. ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The model is also capable of representing a full range of conventional and novel electricity resources, including thermal generators, variable renewable resources (wind and solar), run-of-river, reservoir and pumped-storage hydroelectric generators, energy storage devices, demand-side flexibility, demand response, and several advanced technologies such as long-duration energy storage.","category":"page"},{"location":"User_Guide/workflow/#Workflow","page":"Overall workflow","title":"Workflow","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The flexibility of GenX is achieved through a modular and transparent code structure developed in Julia + JuMP. The software workflow includes two main steps: ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Model configuration and building: this step involves the specification of the planning problem to be studied, including time dependent data like electricity demand, renewable energy availability and fuel prices, number and type of resources included in the model, graph representation of the transmission network, and the set of constraints and objectives to be imposed.\nModel execution: once the model is configured, a solver is called to find the optimal solution to the planning problem. The solution is then post-processed to generate a set of output files that can be used for further analysis.","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The next sections in this guide provide more details on how to perform all the steps in the workflow: ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Model settings parameters: genx_settings.yml\nSolver Configuration: [solver_name]_settings.yml\nGenX Inputs\nTime-domain reduction: time_domain_reduction.yml (optional)\nMulti-stage setup: multi_stage_settings.yml (optional)\nRunning the model\nGenX Outputs","category":"page"},{"location":"User_Guide/workflow/#Details-of-running-a-GenX-case","page":"Overall workflow","title":"Details of running a GenX case","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"This section details as to what happens in the process of running a GenX case. As a first step, the GenX package and the desired solver (is it's anyting other than the default solver, HiGHS; for instance, Gurobi) are loaded ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"using GenX\nusing Gurobi\noptimizer=Gurobi.Optimizer","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The next command the user needs to run is the following:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"run_genx_case!(\"\", optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Contingent upon whether a single stage model or a multi-stage model is intended to be run, the above function, inturn makes calls to either of these two functions: For single-stage case:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"run_genx_case_simple!(case, mysetup, optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"From within this function, if time-domain reduction (TDR) is needed, GenX first checks \twhether there already is time domain clustered data (in order to avoid duplication of efforts) by running ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"prevent_doubled_timedomainreduction(case)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"and if the function","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"!time_domain_reduced_files_exist(TDRpath)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"returns true value, it then runs","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"cluster_inputs(case, settings_path, mysetup)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"to generate the time-domain clustered data for the time-series. -OR- For multi-stage case:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"run_genx_case_multistage!(case, mysetup, optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"In this case also, the TDR clustering is done in a similar way, exxcept for the fact that if TDRSettingsDict[\"MultiStageConcatenate\"] is set to 0, the TDR clustering is done individually for each stage. Otherwise, the clustering is done for all the stages together. The next step is configuring the solver, which is done by","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"OPTIMIZER = configure_solver(settings_path, optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The call to configure_solver first gets the particular solver that is being used to solve the particular case at hand, which then calls a function specific to that solver in order to use either the default values of the solver settings parameter or, any other set of values, specified in the settings YAML file for that particular solver. ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The configuration of solver is followed by loading the input files by running the following function:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"myinputs = load_inputs(mysetup, case)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The above function in its turn calls separate functions to load different resources, demand data, fuels data etc. and returns the dictionary myinputs populated by the input data. The next function call is to generate the model ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"time_elapsed = @elapsed EP = generate_model(mysetup, myinputs, OPTIMIZER)\nprintln(\"Time elapsed for model building is\")\nprintln(time_elapsed)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The above function call instantiates the different decision variables, constraints, and objective function expressions from the input data. It can be seen that we also keep track of the time required to build the model. Follwoing this, the solve_model function makes the call to the solver and return the results as well as the solve time. ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"EP, solve_time = solve_model(EP, mysetup)\nmyinputs[\"solve_time\"] = solve_time # Store the model solve time in myinputs","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"For writing the results, we invoke the following function:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"outputs_path = get_default_output_folder(case)\nelapsed_time = @elapsed outputs_path = write_outputs(EP, outputs_path, mysetup, myinputs)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The call to the writeoutputs() function in turn calls a series of functions (writecapacity, write_power etc.) each of which querries the respective decision variables and creates dataframes, eventually outputting the results to separate CSV files. ","category":"page"},{"location":"User_Guide/workflow/#Single-and-Multi-stage-investment-planning","page":"Overall workflow","title":"Single and Multi-stage investment planning","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"In addition to the standard single-stage planning mode, in which the produces a single snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions, recent improvements in the GenX source code (part of v0.3 release) enable its use for studying long-term evolution of the power system across multiple investment stages. GenX can be used to study multi-stage power system planning in the following two ways:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here.\nThe user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as \"myopic\" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.","category":"page"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/#Curtailable-Variable-Renewables","page":"Curtailable Variable Renewable","title":"Curtailable Variable Renewables","text":"","category":"section"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/","page":"Curtailable Variable Renewable","title":"Curtailable Variable Renewable","text":"Modules = [GenX]\nPages = [\"curtailable_variable_renewable.jl\"]","category":"page"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/#GenX.curtailable_variable_renewable!-Tuple{JuMP.Model, Dict, Dict}","page":"Curtailable Variable Renewable","title":"GenX.curtailable_variable_renewable!","text":"curtailable_variable_renewable!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the constraints for operation of variable renewable energy (VRE) resources whose output can be curtailed (y in mathcalVRE), such as utility-scale solar PV or wind power resources or run-of-river hydro resources that can spill water. The operational constraints for VRE resources are a function of each technology's time-dependent hourly capacity factor (or availability factor, rho^max_yzt), in per unit terms, and the total available capacity (Delta^total_yz).\n\nPower output in each time step For each VRE technology type y and model zone z, the model allows for incorporating multiple bins with different parameters for resource quality (rho^max_yzt), maximum availability (overlineOmega_yz) and investment cost (Pi^INVEST_yz, for example, due to interconnection cost differences). We define variables related to installed capacity (Delta_yz) and retired capacity (Delta_yz) for all resource bins for a particular VRE resource type y and zone z (overlinemathcalVRE^yz). However, the variable corresponding to power output in each timestep is only defined for the first bin. Parameter VREIndex_yz, is used to keep track of the first bin, where VREIndex_yz=1 for the first bin and VREIndex_yz=0 for the remaining bins. This approach allows for modeling many different bins per VRE technology type and zone while significantly reducing the number of operational variable (related to power output for each time step from each bin) added to the model with every additional bin. Thus, the maximum power output for each VRE resource type in each zone is given by the following equation:\n\nbeginaligned\n\tTheta_yzt leq sum_(xz)in overlinemathcalVRE^xzrho^max_xzt times Delta^total_xz hspace2 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\nThe above constraint is defined as an inequality instead of an equality to allow for VRE power output to be curtailed if desired. This adds the possibility of introducing VRE curtailment as an extra degree of freedom to guarantee that generation exactly meets demand in each time step. Note that if OperationalReserves=1 indicating that frequency regulation and operating reserves are modeled, then this function calls curtailable_variable_renewable_operational_reserves!(), which replaces the above constraints with a formulation inclusive of reserve provision.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/#GenX.curtailable_variable_renewable_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Curtailable Variable Renewable","title":"GenX.curtailable_variable_renewable_operational_reserves!","text":"curtailable_variable_renewable_operational_reserves!(EP::Model, inputs::Dict)\n\nWhen modeling operating reserves, this function is called by curtailable_variable_renewable(), which modifies the constraint for maximum power output in each time step from VRE resources to account for procuring some of the available capacity for frequency regulation (f_yzt) and upward operating (spinning) reserves (r_yzt).\n\nbeginaligned\n\tTheta_yzt + f_yzt + r_yzt leq sum_(xz)in overlinemathcalVRE^xzrho^max_xzttimes Delta^total_xz hspace01 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\nThe amount of downward frequency regulation reserves also cannot exceed the current power output.\n\nbeginaligned\n\tf_yzt leq Theta_yzt\n\tforall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\nThe amount of frequency regulation and operating reserves procured in each time step is bounded by the user-specified fraction (upsilon^reg_yz,upsilon^rsv_yz) of available capacity in each period for each reserve type, reflecting the maximum ramp rate for the VRE resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nbeginaligned\n\tr_yzt leq upsilon^rsv_yz sum_(xz)in overlinemathcalVRE^xzrho^max_xzttimes Delta^total_xz hspace1 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT \n\tf_yzt leq upsilon^reg_yz sum_(xz)in overlinemathcalVRE^xzrho^max_xzttimes Delta^total_xz hspace1 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"third_party_genx/#pygenx:-Python-interface-for-GenX","page":"Third Party Extensions","title":"pygenx: Python interface for GenX","text":"","category":"section"},{"location":"third_party_genx/","page":"Third Party Extensions","title":"Third Party Extensions","text":"Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation. ","category":"page"},{"location":"third_party_genx/#Simple-GenX-Case-Runner:-For-automated-sequential-batch-run-for-GenX","page":"Third Party Extensions","title":"Simple GenX Case Runner: For automated sequential batch run for GenX","text":"","category":"section"},{"location":"third_party_genx/","page":"Third Party Extensions","title":"Third Party Extensions","text":"It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner","category":"page"},{"location":"third_party_genx/#Bug-and-feature-requests-and-contact-info","page":"Third Party Extensions","title":"Bug and feature requests and contact info","text":"","category":"section"},{"location":"third_party_genx/","page":"Third Party Extensions","title":"Third Party Extensions","text":"If you would like to report a bug in the code or request a feature, please use our Issue Tracker. If you're unsure or have questions on how to use GenX that are not addressed by the above documentation, please reach out to Sambuddha Chakrabarti (sc87@princeton.edu), Luca Bonaldo (lucabonaldo@princeton.edu), Jesse Jenkins (jdj2@princeton.edu) or Dharik Mallapragada (dharik@mit.edu).","category":"page"},{"location":"User_Guide/running_TDR/#Running-a-case-with-Time-Domain-Reduction","page":"Running the Time-domain Reduction","title":"Running a case with Time Domain Reduction","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"There are two ways to run a case with a reduced (e.g. less than full-year) temporal resolution.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Let GenX perform the time domain reduction before optimizing.\nBring your own clustered data","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"It's also possible for GenX perform clustering separately from the optimization task. ","category":"page"},{"location":"User_Guide/running_TDR/#Method-1:-Let-GenX-perform-the-time-domain-reduction-(clustering)","page":"Running the Time-domain Reduction","title":"Method 1: Let GenX perform the time domain reduction (clustering)","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Set TimeDomainReduction: 1in the GenX settings for the case.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"When the case is run (but before the optimization model is built), reduced time series data will be output to a folder within the case, (typically) TDR_results. Note that if the data already exists in that folder, it will not be overwritten. If a user wants to change the time domain reduction settings and try again, the folder should be deleted before the case is run.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The clustering is done according to the settings in time_domain_reduction.yml. These are described in the Inputs section of data_documentation.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Time domain clustering can only be performed on data which represents a single contiguous period: typically a year of 8760 or 8736 hours.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The header of the file Load_data.csv in the main case folder will typically look like this:","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"..., Rep_Periods, Timesteps_per_Rep_Period, Sub_Weights, ...\n 1, 8760, 8760,","category":"page"},{"location":"User_Guide/running_TDR/#Method-2:-Bring-your-own-clustered-data","page":"Running the Time-domain Reduction","title":"Method 2: Bring your own clustered data","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The second method is to use an external program to generate the reduced ('clustered') time series data. For instance, PowerGenome has a capability to construct GenX cases with clustered time series data.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Running using this method requires setting TimeDomainReduction: 0 in the GenX settings for the case.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Clustered time series data requires specifying the clustering data using three columns in Load_data.csv: Rep_Periods, Timesteps_per_Rep_Period, and Sub_Weights. For example, a problem representing a full year via 3 representative weeks, and where the first week represents one which is twice as common as the others, would look like","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"..., Rep_Periods, Timesteps_per_Rep_Period, Sub_Weights, ...\n 3, 168, 4368.0,\n 2184.0,\n 2184.0,","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"In this example, the first week represents a total of 26*168 = 4368 hours over a full year.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The time series data are written in single unbroken columns: in this example, the Time_Index ranges from 1 to 504.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"For problems involving Long Duration Storage, a file Period_map.csv is necessary to describe how these representative periods occur throughout the modeled year.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"See also the Time-domain reduction.","category":"page"},{"location":"User_Guide/running_TDR/#Performing-time-domain-reduction-(TDR)-separately-from-optimization","page":"Running the Time-domain Reduction","title":"Performing time domain reduction (TDR) separately from optimization","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Added in 0.3.4","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"It may be useful to perform time domain reduction (TDR) (or \"clustering\") on a set of inputs before using them as part of full GenX optimization task. For example, a user might want to test various TDR settings and examine the resulting clustered inputs. This can now be performed using the run_timedomainreduction! function.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"$ julia --project=/home/youruser/GenX\n\njulia> using GenX\njulia> run_timedomainreduction!(\"/path/to/case\")","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"This function will obey the settings in path/to/case/settings/time_domain_reduction_settings.yml. It will output the resulting clustered time series files in the case.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Running this function will overwrite these files in the case. This is done with the expectation that the user is trying out various settings.","category":"page"},{"location":"Model_Reference/Resources/thermal/#Thermal","page":"Thermal","title":"Thermal","text":"","category":"section"},{"location":"Model_Reference/Resources/thermal/","page":"Thermal","title":"Thermal","text":"Modules = [GenX]\nPages = [\"thermal.jl\", \"effective_capacity.jl\"]","category":"page"},{"location":"Model_Reference/Resources/thermal/#GenX.thermal!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal","title":"GenX.thermal!","text":"thermal!(EP::Model, inputs::Dict, setup::Dict)\n\nThe thermal module creates decision variables, expressions, and constraints related to thermal power plants e.g. coal, oil or natural gas steam plants, natural gas combined cycle and combustion turbine plants, nuclear, hydrogen combustion etc. This module uses the following 'helper' functions in separate files: thermal_commit() for thermal resources subject to unit commitment decisions and constraints (if any) and thermal_no_commit() for thermal resources not subject to unit commitment (if any).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal/#GenX.thermal_plant_effective_capacity-Tuple{Any, Any, Vector{Int64}, Int64, Vector{Int64}}","page":"Thermal","title":"GenX.thermal_plant_effective_capacity","text":"thermal_plant_effective_capacity(EP::Model,\n inputs::Dict,\n resources::Vector{Int},\n capres_zone::Int,\n timesteps::Vector{Int})::Matrix{Float64}\n\nEffective capacity in a capacity reserve margin zone for certain resources in the given timesteps.\n\n\n\n\n\n","category":"method"},{"location":"Tutorials/Tutorial_1_configuring_settings/#Tutorial-1:-Configuring-Settings","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"section"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"GenX is easy to customize to fit a variety of problems. In this tutorial, we show which settings are available to change, what their defaults are, and how to change them in your code.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/#What-settings-are-there?","page":"Tutorial 1: Configuring Settings","title":"What settings are there?","text":"","category":"section"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"There are 21 settings available to edit in GenX, found in the file genx_settings.yml. These settings are described at the Model settings parameters page of the documentation. The file is located in the settings folder in the working directory. To change the location of the file, edit the settings_path variable in Run.jl within your directory.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Most settings are set as either 0 or 1, which correspond to whether or not to include a specifc feature. For example, to use TimeDomainReduction, you would set its parameter to 0 within genx_settings.yml. If you would like to run GenX without it, you would set its parameter to 1.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Other settings, such as CO2Cap, have more options corresponding to integers, while some settings such as ModelingtoGenerateAlternativeSlack take a numerical input directly (in this case, the slack value). Two settings, Solver and TimeDomainReductionFolder take in text as input. To learn more about different solvers, read here. For TimeDomainReductionFolder, specify the name of the directory you wish to see the results in. For a more comprehensive description of the input options, see the documentation linked above.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"To see how changing the settings affects the outputs, see Tutorials 3 and 7.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Below is the settings file for example_systems/1_three_zones:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"All genx_settings.yml files in Example_Systems specify most parameters. When configuring your own settings, however, it is not necessary to input all parameters as defaults are specified for each one in configure_settings.jl.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"To open genx_settings.yml in Jupyter, use the function YAML.load(open(...)) and navigate to file in the desired directory:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"using YAML\ngenx_settings_SNE = YAML.load(open(\"example_systems/1_three_zones/settings/genx_settings.yml\"))","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":" Dict{Any, Any} with 19 entries:\n \"NetworkExpansion\" => 1\n \"ModelingToGenerateAlternativeIterations\" => 3\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 0\n \"PrintModel\" => 0\n \"TimeDomainReduction\" => 1\n \"Trans_Loss_Segments\" => 1\n \"CapacityReserveMargin\" => 0\n \"ModelingtoGenerateAlternativeSlack\" => 0.1\n \"MethodofMorris\" => 0\n \"StorageLosses\" => 1\n \"MultiStage\" => 0\n \"OverwriteResults\" => 0\n \"UCommit\" => 2\n \"ModelingToGenerateAlternatives\" => 0\n \"MaxCapReq\" => 0\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"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 example_systems/1_three_zones to contain no parameters:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"new_params = Dict() # Empty dictionary\nYAML.write_file(\"example_systems/1_three_zones/settings/genx_settings.yml\", new_params)","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"The empty file will look like this:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Now, we run GenX and output the file capacity.csv from the Results folder. To do this, we use the function include, which takes a .jl file and runs it in jupyter notebook:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":" Configuring Settings\n Configuring Solver\n Loading Inputs\n Reading Input CSV Files\n Network.csv Successfully Read!\n Demand (load) data Successfully Read!\n Fuels_data.csv Successfully Read!\n\n\n [ Info: Thermal.csv Successfully Read.\n [ Info: Vre.csv Successfully Read.\n [ Info: Storage.csv Successfully Read.\n [ Info: Resource_minimum_capacity_requirement.csv Successfully Read.\n\n Summary of resources loaded into the model:\n -------------------------------------------------------\n \tResource type \t\tNumber of resources\n =======================================================\n \tThermal \t\t3\n \tVRE \t\t4\n \tStorage \t\t3\n =======================================================\n Total number of resources: 10\n -------------------------------------------------------\n Generators_variability.csv Successfully Read!\n Validating time basis\n CSV Files Successfully Read In From GenX-Tutorials/Tutorials/example_systems/1_three_zones\n Generating the Optimization Model\n Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Fuel Module\n CO2 Module\n Investment Transmission Module\n Transmission Module\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (No Unit Commitment) Resources Module\n Time elapsed for model building is\n 5.677411542\n Solving Model\n Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 402430 rows, 306077 cols, 1216044 nonzeros\n 334406 rows, 273093 cols, 1179498 nonzeros\n Presolve : Reductions: rows 334406(-208720); columns 273093(-217481); elements 1179498(-265378)\n Solving the presolved LP\n IPX model has 334406 rows, 273093 columns and 1179498 nonzeros\n Input\n Number of variables: 273093\n Number of free variables: 0\n Number of constraints: 334406\n Number of equality constraints: 54616\n Number of matrix entries: 1179498\n Matrix range: [4e-07, 1e+01]\n RHS range: [7e+02, 2e+04]\n Objective range: [1e-01, 1e+05]\n Bounds range: [2e+00, 2e+04]\n Preprocessing\n Dualized model: no\n Number of dense columns: 13\n Range of scaling factors: [5.00e-01, 1.00e+00]\n IPX version 1.0\n Interior Point Solve\n Iter P.res D.res P.obj D.obj mu Time\n 0 7.92e+03 4.68e+04 3.32147673e+12 -5.29874805e+12 3.77e+08 0s\n 1 2.52e+03 9.09e+03 -3.25877734e+12 -7.21381041e+12 1.13e+08 0s\n 2 4.85e+02 2.35e+03 -3.11396725e+11 -5.19621090e+12 2.79e+07 1s\n 3 3.29e+02 3.98e+02 -1.38395149e+11 -1.60011105e+12 1.06e+07 4s\n Constructing starting basis...\n 4 2.79e+02 2.18e+02 -9.20089553e+10 -1.12770108e+12 6.86e+06 21s\n 5 9.53e+00 7.39e+01 9.91668627e+10 -5.58589863e+11 1.62e+06 24s\n 6 3.40e+00 1.42e+01 5.89999652e+10 -1.16297421e+11 3.82e+05 34s\n 7 9.22e-01 2.82e+00 3.17189476e+10 -3.28274389e+10 1.18e+05 39s\n 8 3.21e-01 9.06e-01 1.54947223e+10 -9.43126058e+09 4.16e+04 44s\n 9 1.43e-01 7.07e-02 1.25444514e+10 -2.07076014e+09 2.26e+04 50s\n 10 7.24e-02 2.69e-02 9.56770103e+09 6.98368943e+08 1.36e+04 59s\n 11 5.85e-02 2.34e-02 9.04050442e+09 9.72471748e+08 1.23e+04 76s\n 12 4.07e-02 1.86e-02 8.41352551e+09 1.36107427e+09 1.07e+04 91s\n 13 2.13e-02 1.04e-02 7.27813663e+09 2.37139743e+09 7.40e+03 106s\n 14 1.23e-02 9.58e-03 6.85995182e+09 2.42302634e+09 6.65e+03 121s\n 15 6.29e-03 8.69e-03 6.30996161e+09 2.53750169e+09 5.63e+03 137s\n 16 5.05e-03 4.32e-03 6.20375634e+09 3.06005287e+09 4.69e+03 153s\n 17 3.10e-03 2.90e-03 5.81685189e+09 3.42321619e+09 3.56e+03 171s\n 18 2.46e-03 1.90e-03 5.69010358e+09 3.69724506e+09 2.97e+03 193s\n 19 2.17e-03 1.40e-03 5.64332584e+09 3.92063823e+09 2.56e+03 211s\n 20 1.68e-03 1.08e-03 5.58574539e+09 4.00019716e+09 2.36e+03 225s\n 21 1.67e-03 1.03e-03 5.58471864e+09 3.99434084e+09 2.36e+03 239s\n 22 1.62e-03 7.41e-04 5.57432205e+09 4.11610384e+09 2.17e+03 253s\n 23 1.30e-03 5.69e-04 5.49997107e+09 4.19795422e+09 1.94e+03 271s\n 24 1.30e-03 5.50e-04 5.49974396e+09 4.19969138e+09 1.93e+03 290s\n 25 1.02e-03 2.93e-04 5.41913926e+09 4.35952658e+09 1.57e+03 303s\n 26 7.07e-04 2.24e-04 5.30762980e+09 4.42283116e+09 1.31e+03 348s\n 27 6.98e-04 2.04e-04 5.30566881e+09 4.42740669e+09 1.30e+03 368s\n 28 5.75e-04 1.34e-04 5.25404059e+09 4.51834486e+09 1.09e+03 384s\n 29 5.11e-04 5.18e-05 5.23316215e+09 4.57449214e+09 9.78e+02 422s\n 30 3.06e-04 3.13e-05 5.11136554e+09 4.65641695e+09 6.75e+02 463s\n 31 2.48e-04 2.50e-05 5.07790558e+09 4.68190888e+09 5.88e+02 556s\n 32 2.26e-04 1.93e-05 5.07281283e+09 4.69130536e+09 5.66e+02 578s\n 33 1.57e-04 9.24e-06 5.02737766e+09 4.76799355e+09 3.85e+02 610s\n 34 9.42e-05 6.90e-06 4.99047612e+09 4.78396507e+09 3.06e+02 633s\n 35 9.03e-05 5.12e-06 4.98763526e+09 4.80106034e+09 2.77e+02 662s\n 36 3.98e-05 2.82e-06 4.94599392e+09 4.83065342e+09 1.71e+02 671s\n 37 2.58e-05 2.14e-06 4.93651437e+09 4.83728484e+09 1.47e+02 682s\n 38 2.50e-05 1.47e-06 4.93618595e+09 4.83982232e+09 1.43e+02 693s\n 39 2.07e-05 1.07e-06 4.93270993e+09 4.84546499e+09 1.29e+02 703s\n 40 1.99e-05 9.16e-07 4.93246702e+09 4.84544485e+09 1.29e+02 712s\n 41 1.27e-05 5.14e-07 4.92622155e+09 4.85308727e+09 1.08e+02 749s\n 42 6.18e-06 2.78e-07 4.91448823e+09 4.86733398e+09 6.98e+01 756s\n 43 5.75e-06 2.48e-07 4.91402422e+09 4.86791504e+09 6.83e+01 768s\n 44 3.92e-06 2.41e-07 4.91163152e+09 4.86829302e+09 6.42e+01 772s\n 45 3.73e-06 2.31e-07 4.91112985e+09 4.86905244e+09 6.23e+01 776s\n 46 1.94e-06 1.39e-07 4.90762167e+09 4.87412061e+09 4.96e+01 779s\n 47 1.92e-06 1.37e-07 4.90757967e+09 4.87423812e+09 4.94e+01 783s\n 48 1.25e-06 1.12e-07 4.90638638e+09 4.87546419e+09 4.58e+01 787s\n 49 7.47e-07 8.85e-08 4.90346514e+09 4.87810372e+09 3.75e+01 790s\n 50 6.48e-07 7.92e-08 4.90314008e+09 4.87888853e+09 3.59e+01 794s\n 51 4.98e-07 6.91e-08 4.90218004e+09 4.88024918e+09 3.25e+01 797s\n 52 4.95e-07 6.83e-08 4.90215919e+09 4.88024410e+09 3.24e+01 801s\n 53 4.90e-07 6.80e-08 4.90216775e+09 4.88028007e+09 3.24e+01 804s\n 54 4.36e-07 6.78e-08 4.90188796e+09 4.88043523e+09 3.18e+01 806s\n 55 2.99e-07 6.38e-08 4.90162529e+09 4.88076205e+09 3.09e+01 809s\n 56 1.58e-07 4.39e-08 4.90042224e+09 4.88323839e+09 2.54e+01 811s\n 57 1.34e-07 4.22e-08 4.90059270e+09 4.88334431e+09 2.55e+01 813s\n 58 1.04e-07 3.50e-08 4.90003483e+09 4.88459728e+09 2.29e+01 815s\n 59 9.50e-08 3.37e-08 4.90009649e+09 4.88472024e+09 2.28e+01 818s\n 60 8.60e-08 3.33e-08 4.90001976e+09 4.88479577e+09 2.25e+01 820s\n 61 7.03e-08 2.51e-08 4.89985257e+09 4.88580810e+09 2.08e+01 823s\n 62 5.25e-08 2.49e-08 4.89952348e+09 4.88588451e+09 2.02e+01 825s\n 63 4.41e-08 2.20e-08 4.89936497e+09 4.88640830e+09 1.92e+01 827s\n 64 1.95e-08 2.05e-08 4.89921316e+09 4.88671585e+09 1.85e+01 829s\n 65 1.85e-08 2.04e-08 4.89917163e+09 4.88677402e+09 1.84e+01 831s\n 66 9.08e-09 1.50e-08 4.89794260e+09 4.88826475e+09 1.43e+01 832s\n 67 3.26e-09 1.41e-08 4.89826703e+09 4.88831416e+09 1.47e+01 834s\n 68 2.55e-09 9.27e-09 4.89776323e+09 4.89045614e+09 1.08e+01 836s\n 69 4.15e-10 6.43e-09 4.89731419e+09 4.89088355e+09 9.52e+00 838s\n 70 9.46e-11 6.14e-09 4.89657446e+09 4.89107504e+09 8.14e+00 840s\n 71 7.28e-12 2.97e-09 4.89649409e+09 4.89256997e+09 5.81e+00 842s\n 72 8.60e-12 2.23e-09 4.89597151e+09 4.89267917e+09 4.87e+00 844s\n 73 7.28e-12 1.47e-09 4.89583195e+09 4.89300343e+09 4.19e+00 845s\n 74 7.42e-12 1.28e-09 4.89583188e+09 4.89303732e+09 4.14e+00 847s\n 75 7.03e-12 1.11e-09 4.89582547e+09 4.89341063e+09 3.57e+00 849s\n 76 7.28e-12 6.11e-10 4.89574070e+09 4.89395382e+09 2.65e+00 850s\n 77 5.46e-12 1.48e-09 4.89568118e+09 4.89402122e+09 2.46e+00 852s\n 78 7.28e-12 5.82e-10 4.89555416e+09 4.89441725e+09 1.68e+00 854s\n 79 5.46e-12 9.31e-10 4.89551185e+09 4.89441779e+09 1.62e+00 856s\n 80 7.28e-12 8.00e-10 4.89548266e+09 4.89444930e+09 1.53e+00 858s\n 81 5.46e-12 4.66e-10 4.89540821e+09 4.89457401e+09 1.23e+00 859s\n 82 3.64e-12 4.95e-10 4.89518737e+09 4.89480554e+09 5.65e-01 861s\n 83 7.28e-12 1.03e-09 4.89518640e+09 4.89481077e+09 5.56e-01 864s\n 84 5.46e-12 8.59e-10 4.89516124e+09 4.89485596e+09 4.52e-01 866s\n 85 3.64e-12 5.97e-10 4.89510929e+09 4.89488390e+09 3.34e-01 869s\n 86 3.64e-12 7.28e-10 4.89511555e+09 4.89489396e+09 3.28e-01 870s\n 87 3.64e-12 9.75e-10 4.89509232e+09 4.89493928e+09 2.27e-01 872s\n 88 5.46e-12 1.35e-09 4.89508607e+09 4.89497465e+09 1.65e-01 875s\n 89 5.46e-12 2.34e-09 4.89507160e+09 4.89500290e+09 1.02e-01 877s\n 90 3.64e-12 4.66e-10 4.89506888e+09 4.89501168e+09 8.47e-02 879s\n 91 3.64e-12 8.15e-10 4.89505281e+09 4.89502676e+09 3.86e-02 882s\n 92 7.28e-12 2.90e-09 4.89504804e+09 4.89503126e+09 2.48e-02 884s\n 93 7.28e-12 3.11e-09 4.89504828e+09 4.89503139e+09 2.50e-02 886s\n 94 3.64e-12 3.94e-09 4.89504182e+09 4.89503147e+09 1.53e-02 887s\n 95 7.28e-12 4.55e-09 4.89503900e+09 4.89503404e+09 7.34e-03 889s\n 96 7.28e-12 3.97e-09 4.89503797e+09 4.89503587e+09 3.11e-03 891s\n 97 3.64e-12 7.99e-09 4.89503736e+09 4.89503634e+09 1.50e-03 893s\n 98 3.64e-12 7.41e-09 4.89503673e+09 4.89503642e+09 4.55e-04 895s\n 99 3.64e-12 9.50e-09 4.89503663e+09 4.89503648e+09 2.22e-04 897s\n 100* 3.64e-12 1.32e-08 4.89503652e+09 4.89503651e+09 1.82e-05 899s\n 101* 3.64e-12 1.08e-08 4.89503652e+09 4.89503652e+09 2.25e-06 901s\n 102* 3.64e-12 3.12e-08 4.89503652e+09 4.89503652e+09 1.34e-07 903s\n 103* 3.64e-12 1.51e-08 4.89503652e+09 4.89503652e+09 8.82e-09 905s\n Running crossover as requested\n Primal residual before push phase: 1.27e-04\n Dual residual before push phase: 5.11e-05\n Number of dual pushes required: 103575\n Number of primal pushes required: 6498\n Summary\n Runtime: 905.57s\n Status interior point solve: optimal\n Status crossover: optimal\n objective value: 4.89503652e+09\n interior solution primal residual (abs/rel): 6.64e-11 / 3.97e-15\n interior solution dual residual (abs/rel): 1.48e-08 / 1.05e-13\n interior solution objective gap (abs/rel): 1.62e-03 / 3.31e-13\n basic solution primal infeasibility: 8.04e-10\n basic solution dual infeasibility: 2.05e-12\n Ipx: IPM optimal\n Ipx: Crossover optimal\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n IPM iterations: 103\n Crossover iterations: 12550\n Objective value : 4.8950365168e+09\n LP solved for primal\n Writing Output\n Time elapsed for writing costs is\n 1.118419208\n Time elapsed for writing capacity is\n 0.3498405\n Time elapsed for writing power is\n 0.784041083\n Time elapsed for writing charge is\n 0.317718542\n Time elapsed for writing capacity factor is\n 0.262756083\n Time elapsed for writing storage is\n 0.144432875\n Time elapsed for writing curtailment is\n 0.235764667\n Time elapsed for writing nse is\n 0.673588083\n Time elapsed for writing power balance is\n 0.533529375\n Time elapsed for writing transmission flows is\n 0.111765375\n Time elapsed for writing transmission losses is\n 0.139880458\n Time elapsed for writing emissions is\n 0.244327417\n Time elapsed for writing reliability is\n 0.163886125\n Time elapsed for writing storage duals is\n 0.43827175\n Time elapsed for writing fuel consumption is\n 0.50627925\n Time elapsed for writing co2 is\n 0.173650209\n Time elapsed for writing price is\n 0.07908475\n Time elapsed for writing energy revenue is\n 0.251686916\n Time elapsed for writing charging cost is\n 0.174489958\n Time elapsed for writing subsidy is\n 0.188284041\n Time elapsed for writing time weights is\n 0.050749417\n Time elapsed for writing net revenue is\n 0.797592334\n Wrote outputs to GenX-Tutorials/Tutorials/example_systems/1_three_zones/results\n Time elapsed for writing is\n 8.276978416","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"The function Run.jl will build and then solve the model according to the specified parameters. These results will then be output into a results folder in the same directory. Note that the results folders are not overwritten with each run.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"using CSV\nusing DataFrames\nresults = CSV.read(open(\"example_systems/1_three_zones/Results/capacity.csv\"),DataFrame)","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"
11×15 DataFrame
RowResourceZoneStartCapRetCapNewCapEndCapCapacityConstraintDualStartEnergyCapRetEnergyCapNewEnergyCapEndEnergyCapStartChargeCapRetChargeCapNewChargeCapEndChargeCap
String31String3Float64Float64Float64Float64String3Float64Float64Float64Float64Float64Float64Float64Float64
1MA_natural_gas_combined_cycle10.00.07394.757394.750.00.00.00.00.00.00.00.00.0
2CT_natural_gas_combined_cycle20.00.02305.822305.820.00.00.00.00.00.00.00.00.0
3ME_natural_gas_combined_cycle30.00.0716.666716.6660.00.00.00.00.00.00.00.00.0
4MA_solar_pv10.00.021186.521186.50.00.00.00.00.00.00.00.00.0
5CT_onshore_wind20.00.011905.511905.50.00.00.00.00.00.00.00.00.0
6CT_solar_pv20.00.016578.816578.80.00.00.00.00.00.00.00.00.0
7ME_onshore_wind30.00.012767.312767.30.00.00.00.00.00.00.00.00.0
8MA_battery10.00.03362.33362.30.00.00.019427.719427.70.00.00.00.0
9CT_battery20.00.05318.365318.360.00.00.027274.127274.10.00.00.00.0
10ME_battery30.00.02095.32095.30.00.00.07096.277096.270.00.00.00.0
11Totaln/a0.00.083631.383631.3n/a0.00.053798.153798.10.00.00.00.0
","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"As you can see, this runs without a problem! To try with your own parameters, edit the new_params dictionary with whatever parameters you'd like to try and run the cells again.Note: to output the results, you'll have to either delete the previous results folder, or input the name of the new results folder (e.g. results_1) when calling CSV.read as above.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Finally, let's rewite genx_settings.yml to put the original settings in the example back: ","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"YAML.write_file(\"example_systems/1_three_zones/settings/genx_settings.yml\", genx_settings_TZ)","category":"page"},{"location":"Model_Reference/Resources/storage_all/#Storage-All","page":"Storage All","title":"Storage All","text":"","category":"section"},{"location":"Model_Reference/Resources/storage_all/","page":"Storage All","title":"Storage All","text":"Modules = [GenX]\nPages = [\"storage_all.jl\"]","category":"page"},{"location":"Model_Reference/Resources/storage_all/#GenX.storage_all!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage All","title":"GenX.storage_all!","text":"storage_all!(EP::Model, inputs::Dict, setup::Dict)\n\nSets up variables and constraints common to all storage resources. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Tutorials/Tutorial_6_solver_settings/#Tutorial-6:-Solver-Settings","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Solver Settings","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Though solving the model relies only on optimize, there are a number of ways to change the way in which the model is optimized. This tutorial goes over solver parameters and how they affect the model solution.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#Table-of-Contents","page":"Tutorial 6: Post Processing","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The HiGHs Solver\nFeasibility Tolerance\nPreSolve\nCrossover","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"using YAML\nusing GenX\nusing JuMP\nusing HiGHS\nusing DataFrames\nusing Plots\nusing Plotly","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"case = joinpath(\"example_systems/1_three_zones\") \n\ngenx_settings = GenX.get_settings_path(case, \"genx_settings.yml\");\nwriteoutput_settings = GenX.get_settings_path(case, \"output_settings.yml\")\nsetup = GenX.configure_settings(genx_settings,writeoutput_settings) \nsettings_path = GenX.get_settings_path(case)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Configuring Settings\n\n \"example_systems/1_three_zones/settings\"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"### Create TDR_Results\nif \"TDR_results\" in cd(readdir,case)\n rm(joinpath(case,\"TDR_results\"), recursive=true) \nend\n\nTDRpath = joinpath(case, setup[\"TimeDomainReductionFolder\"])\nsystem_path = joinpath(case, setup[\"SystemFolder\"])\n\nif setup[\"TimeDomainReduction\"] == 1\n GenX.prevent_doubled_timedomainreduction(system_path)\n if !GenX.time_domain_reduced_files_exist(TDRpath)\n println(\"Clustering Time Series Data (Grouped)...\")\n GenX.cluster_inputs(case, settings_path, setup)\n else\n println(\"Time Series Data Already Clustered.\")\n end\nend\n\ninputs = GenX.load_inputs(setup, case)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#The-HiGHS-Solver","page":"Tutorial 6: Post Processing","title":"The HiGHS Solver","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"In the example files, the solver HiGHS. HiGHS is freely available for all to use. Other solvers, such as Gurobi, are available for free for academics. For the purpose of this tutorial, we will be focusing on HiGHS. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"To set the solver preferences, go into the settings folder of your case and select the YAML file of the solver you're using.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"settings_folder = cd(readdir,joinpath(case,\"Settings\")) # Print Settings folder","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" 7-element Vector{String}:\n \".DS_Store\"\n \"clp_settings.yml\"\n \"cplex_settings.yml\"\n \"genx_settings.yml\"\n \"gurobi_settings.yml\"\n \"highs_settings.yml\"\n \"time_domain_reduction_settings.yml\"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings = YAML.load(open(joinpath(case,\"Settings/highs_settings.yml\")))","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Dict{Any, Any} with 6 entries:\n \"Method\" => \"choose\"\n \"Feasib_Tol\" => 0.1\n \"run_crossover\" => \"on\"\n \"TimeLimit\" => 1.0e23\n \"Optimal_Tol\" => 0.1\n \"Pre_Solve\" => \"choose\"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The function configure_highs in src/configure_solver contains a list of default settings for the HiGHS solver","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"There are about 80, so we'll only focus on a few for now. In most cases, you can leave the other settings on default. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The default settings are combined with the settings you specify in highs_settings.yml in configure_highs, which is called from configure_solver in run_genx_case_simple right before the model is generated.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#Feasibility-Tolerance","page":"Tutorial 6: Post Processing","title":"Feasibility Tolerance","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The parameters Feasib_Tol and Optimal_Tol represent the feasibility of the primal and dual functions respectively. Without going into too much detail, a dual function is an analagous formulation of the original (\"primal\") function whose objective value acts as a lower bound to the primal function. The objective value of the primal function is then the upper bound of the dual function. HiGHS will solve the dual and primal at each time step, then terminate when the solutions of the two are within a certain tolerance range. For more information on how this works specifically in HiGHS, see the HiGHS documentaion. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"If we decrease the tolerance parameters, the objective value becomes closer to the \"true\" optimal value.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# Change tolerance, generate and solve model`\ntols = [1e-7,1e-4,1e-2,1e-1]\nOV = zeros(1,4)\n\nfor i in range(1,length(tols))\n println(\" \")\n println(\"----------------------------------------------------\")\n println(\"Iteration \",i)\n println(\"Tolerance = \",tols[i])\n println(\"----------------------------------------------------\")\n highs_settings[\"Feasib_Tol\"] = tols[i]\n highs_settings[\"Optimal_Tol\"] = tols[i]\n YAML.write_file(joinpath(case,\"settings/highs_settings.yml\"), highs_settings)\n OPTIMIZER1 = GenX.configure_solver(settings_path,HiGHS.Optimizer)\n EP = GenX.generate_model(setup,inputs,OPTIMIZER1)\n GenX.solve_model(EP,setup)\n OV[i] = objective_value(EP)\nend","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Using the smallest tolerance as our base, we can see the error as the tolerance increases:","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"DataFrame([tols[2:end] abs.(OV[2:end] .- OV[1])],[\"Tolerance\", \"Error\"])","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"3×2 DataFrame\n Row\tTolerance\tError\n Float64\t Float64\n ───────────────────────────\n 1\t0.0001\t 0.0\n 2\t0.01\t 1.81899e-12\n 3\t0.1\t 3.45608e-11","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"using Plots\nusing Plotly","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# Plot the error as a function of the tolerance\nplotlyjs()\nPlots.scatter(tols[2:end], abs.(OV[2:end] .- OV[1]),legend=:topleft,\n ylabel=\"Error\", xlabel=\"Tolerance\",size=(920,400),label=:\"Error\",title=\"Tolerance of Solver vs Error\")\nygrid!(:on, :dashdot, 0.1)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#PreSolve","page":"Tutorial 6: Post Processing","title":"PreSolve","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"In optimization, presolve is a stage at the beginning of the solver in which the problem is simplified to remove redunant constraints and otherwise simplify the problem before the optimization itself begins. The default for presolve in GenX is \"choose\", allowing the solver to use presolve only if it will reduce computation time. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Let's try setting presolve to off and on, then compare computation times.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# First, set tolerances back to original\nhighs_settings[\"Feasib_Tol\"] = 1e-5\nhighs_settings[\"Optimal_Tol\"] = 1e-5\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings) ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"Pre_Solve\"] = \"off\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER2 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP2 = GenX.generate_model(setup,inputs,OPTIMIZER2)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 18492\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 5544 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 7398 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 27730 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 2 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 18490 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cCapacityResMargin, cESRShare, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cZoneMaxCapReq, cZoneMinCapReq, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eCapResMarBalance, eCapResMarBalanceStor, eCapResMarBalanceThermal, eCapResMarBalanceVRE, eELOSS, eELOSSByZone, eESR, eESRDischarge, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eMaxCapRes, eMaxCapResInvest, eMinCapRes, eMinCapResInvest, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution2 = @elapsed GenX.solve_model(EP2,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Solving LP without presolve or with basis\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 -4.3842305368e+02 Ph1: 19318(12391.6); Du: 5(438.423) 0s\n 18662 9.5083526285e+03 Pr: 3142(5018.36); Du: 0(0.000872182) 5s\n 23359 9.8583752055e+03 Pr: 0(0); Du: 0(1.27565e-13) 6s\n Model status : Optimal\n Simplex iterations: 23359\n Objective value : 9.8583752055e+03\n HiGHS run time : 6.77\n LP solved for primal\n\n 6.84933975","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"Pre_Solve\"] = \"on\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER3 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP3 = GenX.generate_model(setup,inputs,OPTIMIZER3)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 18492\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 5544 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 7398 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 27730 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 2 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 18490 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cCapacityResMargin, cESRShare, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cZoneMaxCapReq, cZoneMinCapReq, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eCapResMarBalance, eCapResMarBalanceStor, eCapResMarBalanceThermal, eCapResMarBalanceVRE, eELOSS, eELOSSByZone, eESR, eESRDischarge, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eMaxCapRes, eMaxCapResInvest, eMinCapRes, eMinCapResInvest, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution3 = @elapsed GenX.solve_model(EP3,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 35947 rows, 17464 cols, 136177 nonzeros\n 34470 rows, 15991 cols, 136110 nonzeros\n Presolve : Reductions: rows 34470(-6202); columns 15991(-2501); elements 136110(-29848)\n Solving the presolved LP\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 -2.9011432493e+00 Ph1: 118(557.293); Du: 15(2.90114) 0s\n 16445 9.8583752055e+03 Pr: 0(0); Du: 0(1.25316e-13) 4s\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n Simplex iterations: 16445\n Objective value : 9.8583752055e+03\n HiGHS run time : 4.55\n LP solved for primal\n\n 4.655439792","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"As we can see, the runtime with PreSolve is shorter, and would be even shorter for a larger system. However, it could introduce numerical inaccuracies. If you find the model is struggling to converge, try turn PreSolve off.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# Write PreSolve back to choose\nhighs_settings[\"Pre_Solve\"] = \"choose\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#Crossover","page":"Tutorial 6: Post Processing","title":"Crossover","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Crossover is a method in which, at each step of the optimization algorithm, the solution is pushed to the boundary of the solution space. This allows for a potentially more accurate solution, but can be computationally intensive. Let's try turning crossover on and off and see what solutions we get:","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"run_crossover\"] = \"off\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER4 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP4 = GenX.generate_model(setup,inputs,OPTIMIZER4)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Transmission Module\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Minimum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 83192\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 24024 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 20334 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 103509 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 4 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 79492 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxFlow_in, cMaxFlow_out, cMaxLineReinforcement, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cTAuxLimit, cTAuxSum, cTLoss, cZoneMinCapReq, eAvail_Trans_Cap, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eELOSS, eELOSSByZone, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eLosses_By_Zone, eMinCapRes, eMinCapResInvest, eNet_Export_Flows, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceLossesByZone, ePowerBalanceNetExportFlows, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCNetworkExp, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, eTransMax, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vFLOW, vNEW_TRANS_CAP, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vTAUX_NEG, vTAUX_POS, vTLOSS, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution4 = @elapsed GenX.solve_model(EP4,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 123675 rows, 81174 cols, 478190 nonzeros\n 116575 rows, 74076 cols, 478470 nonzeros\n Presolve : Reductions: rows 116575(-31292); columns 74076(-9116); elements 478470(-75676)\n Solving the presolved LP\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 1.9243583242e+03 Pr: 5545(9397.81); Du: 0(3.92542e-09) 0s\n 13530 2.9999821788e+03 Pr: 30131(9.49605e+06); Du: 0(0.0013131) 5s\n 17547 3.5484267823e+03 Pr: 19414(952045); Du: 0(0.00175439) 10s\n 20723 4.7298157079e+03 Pr: 29321(991206); Du: 0(0.00183106) 15s\n 23580 5.7123748112e+03 Pr: 32150(7.12339e+06); Du: 0(0.00148821) 21s\n 26170 6.1864339355e+03 Pr: 23825(7.35638e+06); Du: 0(0.00149712) 26s\n 29149 6.6441899572e+03 Pr: 27775(3.51868e+06); Du: 0(0.00148729) 31s\n 31348 6.8846964690e+03 Pr: 35484(2.8051e+06); Du: 0(0.00139557) 36s\n 33603 6.9920173954e+03 Pr: 24118(2.03558e+06); Du: 0(0.00124593) 42s\n 35671 7.2015870783e+03 Pr: 34108(1.48506e+07); Du: 0(0.00155189) 47s\n 37885 7.4048679609e+03 Pr: 31619(4.35123e+07); Du: 0(0.00179926) 52s\n 40109 7.6356641465e+03 Pr: 25843(2.88592e+06); Du: 0(0.00205301) 58s\n 42353 7.8375259516e+03 Pr: 31443(8.49023e+06); Du: 0(0.00226205) 64s\n 45258 8.1692860958e+03 Pr: 37870(5.26412e+06); Du: 0(0.00255441) 69s\n 48083 8.3152673717e+03 Pr: 40961(1.14875e+07); Du: 0(0.00294817) 75s\n 50545 8.4510258333e+03 Pr: 30790(3.72272e+08); Du: 0(0.00304629) 80s\n 52861 8.5807507297e+03 Pr: 22492(930796); Du: 0(0.00320519) 85s\n 54980 8.6629986832e+03 Pr: 30776(2.08885e+07); Du: 0(0.00337039) 91s\n 57333 8.7549581833e+03 Pr: 26257(1.13046e+06); Du: 0(0.00357615) 96s\n 59389 8.8000584935e+03 Pr: 36678(2.40379e+06); Du: 0(0.00364701) 101s\n 61669 8.8767323679e+03 Pr: 35715(2.44371e+06); Du: 0(0.00390224) 107s\n 63914 8.9782186363e+03 Pr: 43654(3.60725e+06); Du: 0(0.00423026) 113s\n 66084 9.0603325781e+03 Pr: 22220(2.48776e+06); Du: 0(0.00410399) 118s\n 69022 9.1231092369e+03 Pr: 22727(1.78641e+06); Du: 0(0.00444875) 124s\n 71953 9.1538574545e+03 Pr: 22264(5.37124e+06); Du: 0(0.00461629) 129s\n 74846 9.1867207120e+03 Pr: 26970(1.49142e+06); Du: 0(0.00477614) 135s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 77129 9.2058130738e+03 Pr: 1(0.000235421); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n Simplex iterations: 77136\n Objective value : 9.2058130749e+03\n HiGHS run time : 140.51\n LP solved for primal\n\n 140.762363","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"run_crossover\"] = \"on\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER5 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP5 = GenX.generate_model(setup,inputs,OPTIMIZER5)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Transmission Module\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Minimum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 83192\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 24024 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 20334 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 103509 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 4 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 79492 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxFlow_in, cMaxFlow_out, cMaxLineReinforcement, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cTAuxLimit, cTAuxSum, cTLoss, cZoneMinCapReq, eAvail_Trans_Cap, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eELOSS, eELOSSByZone, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eLosses_By_Zone, eMinCapRes, eMinCapResInvest, eNet_Export_Flows, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceLossesByZone, ePowerBalanceNetExportFlows, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCNetworkExp, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, eTransMax, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vFLOW, vNEW_TRANS_CAP, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vTAUX_NEG, vTAUX_POS, vTLOSS, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution5 = @elapsed GenX.solve_model(EP5,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 123675 rows, 81174 cols, 478190 nonzeros\n 116575 rows, 74076 cols, 478470 nonzeros\n Presolve : Reductions: rows 116575(-31292); columns 74076(-9116); elements 478470(-75676)\n Solving the presolved LP\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 1.9243583242e+03 Pr: 5545(9397.81); Du: 0(3.92542e-09) 0s\n 13530 2.9999821788e+03 Pr: 30131(9.49605e+06); Du: 0(0.0013131) 5s\n 17547 3.5484267823e+03 Pr: 19414(952045); Du: 0(0.00175439) 10s\n 20723 4.7298157079e+03 Pr: 29321(991206); Du: 0(0.00183106) 15s\n 23580 5.7123748112e+03 Pr: 32150(7.12339e+06); Du: 0(0.00148821) 21s\n 26170 6.1864339355e+03 Pr: 23825(7.35638e+06); Du: 0(0.00149712) 26s\n 29149 6.6441899572e+03 Pr: 27775(3.51868e+06); Du: 0(0.00148729) 31s\n 31348 6.8846964690e+03 Pr: 35484(2.8051e+06); Du: 0(0.00139557) 36s\n 33603 6.9920173954e+03 Pr: 24118(2.03558e+06); Du: 0(0.00124593) 42s\n 35671 7.2015870783e+03 Pr: 34108(1.48506e+07); Du: 0(0.00155189) 47s\n 37885 7.4048679609e+03 Pr: 31619(4.35123e+07); Du: 0(0.00179926) 52s\n 40109 7.6356641465e+03 Pr: 25843(2.88592e+06); Du: 0(0.00205301) 58s\n 42353 7.8375259516e+03 Pr: 31443(8.49023e+06); Du: 0(0.00226205) 63s\n 45258 8.1692860958e+03 Pr: 37870(5.26412e+06); Du: 0(0.00255441) 69s\n 48083 8.3152673717e+03 Pr: 40961(1.14875e+07); Du: 0(0.00294817) 75s\n 50545 8.4510258333e+03 Pr: 30790(3.72272e+08); Du: 0(0.00304629) 80s\n 52861 8.5807507297e+03 Pr: 22492(930796); Du: 0(0.00320519) 85s\n 54980 8.6629986832e+03 Pr: 30776(2.08885e+07); Du: 0(0.00337039) 91s\n 57333 8.7549581833e+03 Pr: 26257(1.13046e+06); Du: 0(0.00357615) 96s\n 59389 8.8000584935e+03 Pr: 36678(2.40379e+06); Du: 0(0.00364701) 101s\n 61669 8.8767323679e+03 Pr: 35715(2.44371e+06); Du: 0(0.00390224) 107s\n 63914 8.9782186363e+03 Pr: 43654(3.60725e+06); Du: 0(0.00423026) 113s\n 66084 9.0603325781e+03 Pr: 22220(2.48776e+06); Du: 0(0.00410399) 118s\n 69022 9.1231092369e+03 Pr: 22727(1.78641e+06); Du: 0(0.00444875) 124s\n 71953 9.1538574545e+03 Pr: 22264(5.37124e+06); Du: 0(0.00461629) 129s\n 74408 9.1814081583e+03 Pr: 29329(5.2193e+06); Du: 0(0.00473215) 134s\n 77012 9.2060247446e+03 Pr: 0(0); Du: 0(0.00509972) 140s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 77129 9.2058130738e+03 Pr: 1(0.000235421); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n Simplex iterations: 77136\n Objective value : 9.2058130749e+03\n HiGHS run time : 140.44\n LP solved for primal\n\n 140.74829025","category":"page"},{"location":"User_Guide/multi_stage_input/#Multi-stage-setup","page":"Multi-stage Model","title":"Multi-stage setup","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"This section describes the available features, inputs and model components related to formulating and solving multi-stage investment planning problems. Two different types of multi-stage problems can be setup:","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"Perfect foresight: A single multi-stage investment planning problem that simultaneously optimizes capacity and operations across all specified investment stages\nMyopic: Sequential solution of single-stage investment planning for each investment stage, where capacity additions and retirements from the previous stages are used to determine initial (or existing) capacity at the beginning of the current stage. ","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"The table below summarizes the key differences in the two model setups.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" Perfect foresight Myopic\nNo. of optimization problems solved 1 Equal to number of investment stages\nObjective function cost basis Net present value Annualized costs\nPrice/dual variable information available? No Yes","category":"page"},{"location":"User_Guide/multi_stage_input/#Additional-inputs-needed-for-multi-stage-modeling","page":"Multi-stage Model","title":"Additional inputs needed for multi-stage modeling","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/#Input-data-files","page":"Multi-stage Model","title":"Input data files","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"Instead of one set of input files, there is one directory of input files that needs to be provided for each planning period or stage (e.g., “inputs/inputs_p1/” for the first period “inputs/inputs_p2/” for the second period, etc.). Below we list the additional parameters that must be provided in the corresponding stage-specific input files to instantiate a multi-stage planning problem.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" Resourcemultistagedata.csv files\nMin_Retired_Cap_MW Minimum capacity in MW that must retire in this planning stage. Note that for the co-located VRE-STOR module, this value represents the grid connection component.\nMin_Retired_Energy_Cap_MW Minimum energy capacity in MW that must retire in this planning stage. Note that for the co-located VRE-STOR module, this value represents the storage component.\nMin_Retired_Charge_Cap_MW Minimum charge capacity in MW that must retire in this planning stage.\nLifetime The operational lifespan in years of this technology after which it must be retired.\nCapital_Recovery_Period The technology-specific period in years over which initial capital costs must be recovered. Note that for the co-located VRE-STOR module, this value represents the grid connection component.\nWACC The technology-specific weighted average cost of capital. Note that for the co-located VRE-STOR module, this value represents the grid connection component.\nContribute_Min_Retirement {0, 1}, Flag to indicate whether the (retrofitting) resource can contribute to the minimum retirement requirement.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" co-located VRE-STOR resources only\nMin_Retired_Cap_Inverter_MW Minimum inverter capacity in MW AC that must retire in this plannig stage.\nMin_Retired_Cap_Solar_MW Minimum solar PV capacity in MW DC that must retire in this plannig stage.\nMin_Retired_Cap_Wind_MW Minimum wind capacity in MW AC that must retire in this plannig stage.\nMin_Retired_Cap_DischargeDC\\MW Minimum storage DC discharge capacity that must retire in this planning stage with STOR_DC_DISCHARGE = 2.\nMin_Retired_Cap_ChargeDC\\MW Minimum storage DC charge capacity that must retire in this planning stage with STOR_DC_CHARGE = 2.\nMin_Retired_Cap_DischargeAC\\MW Minimum storage AC discharge capacity that must retire in this planning stage with STOR_AC_DISCHARGE = 2.\nMin_Retired_Cap_ChargeAC\\MW Minimum storage AC charge capacity that must retire in this planning stage with STOR_AC_CHARGE = 2.\nCapital_Recovery_Period_DC The technology-specific period in years over which initial capital costs for the inverter component must be recovered.\nCapital_Recovery_Period_Solar The technology-specific period in years over which initial capital costs for the solar PV component must be recovered.\nCapital_Recovery_Period_Wind The technology-specific period in years over which initial capital costs for the wind component must be recovered.\nCapital_Recovery_PeriodDischargeDC The technology-specific period in years over which initial capital costs for the storage DC discharge component must be recovered when STOR_DC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeDC The technology-specific period in years over which initial capital costs for the storage DC charge component must be recovered when STOR_DC_CHARGE = 2.\nCapital_Recovery_PeriodDischargeAC The technology-specific period in years over which initial capital costs for the storage AC discharge component must be recovered when STOR_AC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeAC The technology-specific period in years over which initial capital costs for the storage AC charge component must be recovered when STOR_DC_CHARGE = 2.\nWACC_DC The line-specific weighted average cost of capital for the inverter component.\nWACC_Solar The line-specific weighted average cost of capital for the solar PV component.\nWACC_Wind The line-specific weighted average cost of capital for the wind component.\nWACC_Discharge_DC The line-specific weighted average cost of capital for the discharging DC storage component with STOR_DC_DISCHARGE = 2.\nWACC_Charge_DC The line-specific weighted average cost of capital for the charging DC storage component with STOR_DC_CHARGE = 2.\nWACC_Discharge_AC The line-specific weighted average cost of capital for the discharging AC storage component with STOR_AC_DISCHARGE = 2.\nWACC_Charge_AC The line-specific weighted average cost of capital for the charging AC storage component with STOR_AC_CHARGE = 2.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" Network.csv\nLine_Max_Flow_Possible_MW The maximum transmission capacity of the line, as opposed to Line_Max_Reinforcement_MW which now specifies the maximum expansion to the line in one stage.\nCapital_Recovery_Period The line-specific period in years over which initial capital costs must be recovered.\nWACC The line-specific weighted average cost of capital.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"note: Allowing retrofitted capacity to not contribute to minimum retirement requirements (`myopic=0` only)\nSpecial considerations must be taken into account when utilizing the retrofit module alongside multi-stage planning, particularly when using a non zero value for the Min_Retired_Cap_MW column in the Resource_multistage_data.csv file.When assigning a non-zero value to the Min_Retired_Cap_MW column in the Resource_multistage_data.csv file, the user can specify whether the model should consider the retrofitted capacity to contribute to the minimum retirement requirement. This is done by setting the Contribute_Min_Retirement column to 1 for the retrofit options in the same retrofit cluster (i.e., same Retrofit_Id).\nBy default, the model assumes that retrofitted capacity contributes to fulfilling minimum retirement requirements.\nShould users wish to exclude retrofitted capacity from contributing to minimum retirement requirements, they must set the Contribute_Min_Retirement column to 0 for all retrofit options within the same retrofit cluster (i.e., sharing the same Retrofit_Id).\nIt's important to note that this additional functionality is not currently supported when myopic=1. In this case, the retrofit options are only allowed to contribute to the minimum retirement requirement.Example 1: Retrofitted capacity is allowed to contribute to the minimum retirement requirement (i.e., retrofit options in the same cluster (Retrofit_Id = 1) all have Contribute_Min_Retirement = 1):Thermal.csv\n\nResource │ Zone | Retrofit | Can_Retrofit | Retrofit_Id | Retrofit_Efficiency\nString │ Int64 | Int64 | Int64 | Int64 | Float64\n─────────────────-┼───────┼─────────────────────────┼────────────-┼────────────────────\ncoal_1 │ 1 │ 0 │ 1 │ 1 │ 0\n20_NH3_retrofit_1 │ 1 │ 1 │ 0 │ 1 │ 0.85\n20_NH3_retrofit_2 │ 1 │ 1 │ 0 │ 1 │ 0.85Resource_multistage_data.csv\n\nResource │ Min_Retired_Cap_MW | Contribute_Min_Retirement\nString │ Float64 | Float64 \n─────────────────-┼────────────────────┼──────────────────────────\ncoal_1 │ 4500 │ 0\n20_NH3_retrofit_1 │ 0 │ 1 <---------\n20_NH3_retrofit_2 │ 0 │ 1 <---------Example 2: Retrofitted capacity is not allowed to contribute to the minimum retirement requirement (i.e., none of the retrofit options in the same cluster (Retrofit_Id = 1) contribute to the minimum retirement requirement (myopic=0)):Thermal.csv: same as Example 1.Resource_multistage_data.csv\n\nResource │ Min_Retired_Cap_MW | Contribute_Min_Retirement\nString │ Float64 | Float64\n─────────────────-┼────────────────────┼──────────────────────────\ncoal_1 │ 4500 │ 0\n20_NH3_retrofit_1 │ 0 │ 0 <---------\n20_NH3_retrofit_2 │ 0 │ 0 <---------And the case where some retrofit options contribute to the minimum retirement requirement and some do not is not currently supported and will be addressed in a future release.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"warning: Warning\nIf 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. ","category":"page"},{"location":"User_Guide/multi_stage_input/#Settings-Files","page":"Multi-stage Model","title":"Settings Files","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"A separate settings.yml file includes a list of parameters to be specified to formulate the multi-stage planning model.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" multi_stage_settings.yml\nNumStages The number of model investment planning stages.\nStageLengths A list of lengths of each model stage in years (e.g., [10, 10, 10] for three stages each of length 10). Note that stages could be defined to be of varying length.\nMyopic 0 = perfect foresight, 1 = myopic model (see above table)\nConvergenceTolerance The relative optimality gap used for convergence of the dual dynamic programming algorithm. Only required when Myopic = 0\nWACC Rate used to discount non-technology-specific costs from stage to stage (i.e., the “social discount rate”).","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" time_domain_reduction_settings.yml\nMultiStageConcatenate Designates whether to use time domain reduction for the full set of input data together (1) or to reduce only the first stage data and apply the returned representative periods to the rest of the input data (0).","category":"page"},{"location":"User_Guide/solver_configuration/#Solver-Configuration","page":"Solver Configuration","title":"Solver Configuration","text":"","category":"section"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"To define and solve the optimization problems, GenX relies on JuMP, a domain-specific modeling language for mathematical optimization written in Julia, and on a variety of open-source and commercial solvers. GenX supports the following solvers:","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"Cbc (open-source)\nClp (open-source)\nCPLEX (commercial)\nGurobi (commercial)\nHiGHS (open-source)\nSCIP (open-source)","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"Solver related settings parameters are specified in the appropriate .yml file (e.g. highs_settings.yml, gurobi_settings.yml, etc.), which should be located in the settings folder inside the current working directory (the same settings folder where genx_settings.yml is located). Settings are specific to each solver. Check the Example_Systems folder for examples of solver settings files and parameters. ","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"note: Note\nGenX supplies default settings for most solver settings in the various solver-specific functions found in the src/configure_solver/ directory. To overwrite default settings, you can specify the below Solver specific settings.","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"The following table summarizes the solver settings parameters and their default/possible values. ","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"tip: Tip\nSince each solver has its own set of parameters names, together with a description of the parameter, the table provides a reference to the the corresponding solver specific parameter name. ","category":"page"},{"location":"User_Guide/solver_configuration/#Solver-settings-parameters**","page":"Solver Configuration","title":"Solver settings parameters**","text":"","category":"section"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"Settings Parameter Description\nMethod Algorithm used to solve continuous models or the root node of a MIP model. Generally, barrier method provides the fastest run times for real-world problem set.\n CPLEX: CPX_PARAM_LPMETHOD - Default = 0; See link for more specifications.\n Gurobi: Method - Default = -1; See link for more specifications.\n clp: SolveType - Default = 5; See link for more specifications.\n HiGHS: Method - Default = \"choose\"; See link for more specifications.\nBarConvTol Convergence tolerance for barrier algorithm.\n CPLEX: CPX_PARAM_BAREPCOMP - Default = 1e-8; See link for more specifications.\n Gurobi: BarConvTol - Default = 1e-8; See link for more specifications.\nFeasib_Tol All constraints must be satisfied as per this tolerance. Note that this tolerance is absolute.\n CPLEX: CPX_PARAM_EPRHS - Default = 1e-6; See link for more specifications.\n Gurobi: FeasibilityTol - Default = 1e-6; See link for more specifications.\n clp: PrimalTolerance - Default = 1e-7; See link for more specifications.\n clp: DualTolerance - Default = 1e-7; See link for more specifications.\nOptimal_Tol Reduced costs must all be smaller than Optimal_Tol in the improving direction in order for a model to be declared optimal.\n CPLEX: CPX_PARAM_EPOPT - Default = 1e-6; See link for more specifications.\n Gurobi: OptimalityTol - Default = 1e-6; See link for more specifications.\nPre_Solve Controls the presolve level.\n Gurobi: Presolve - Default = -1; See link for more specifications.\n clp: PresolveType - Default = 5; See link for more specifications.\nCrossover Determines the crossover strategy used to transform the interior solution produced by barrier algorithm into a basic solution.\n CPLEX: CPX_PARAM_SOLUTIONTYPE - Default = 2; See link for more specifications.\n Gurobi: Crossover - Default = 0; See link for more specifications.\nNumericFocus Controls the degree to which the code attempts to detect and manage numerical issues.\n CPLEX: CPX_PARAM_NUMERICALEMPHASIS - Default = 0; See link for more specifications.\n Gurobi: NumericFocus - Default = 0; See link for more specifications.\nTimeLimit Time limit to terminate the solution algorithm, model could also terminate if it reaches MIPGap before this time.\n CPLEX: CPX_PARAM_TILIM- Default = 1e+75; See link for more specifications.\n Gurobi: TimeLimit - Default = infinity; See link for more specifications.\n clp: MaximumSeconds - Default = -1; See link for more specifications.\nMIPGap Optimality gap in case of mixed-integer program.\n CPLEX: CPX_PARAM_EPGAP- Default = 1e-4; See link for more specifications.\n Gurobi: MIPGap - Default = 1e-4; See link for more specifications.\nDualObjectiveLimit When using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit.\n clp: DualObjectiveLimit - Default = 1e308; See link for more specifications.\nMaximumIterations Terminate after performing this number of simplex iterations.\n clp: MaximumIterations - Default = 2147483647; See link for more specifications.\nLogLevel Set to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output.\n clp: logLevel - Default = 1; See link for more specifications.\n cbc: logLevel - Default = 1; See link for more specifications.\nInfeasibleReturn Set to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well).\n clp: InfeasibleReturn - Default = 0; See link for more specifications.\nScaling Sets or unsets scaling; 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic(later).\n clp: Scaling - Default = 3; See link for more specifications.\nPerturbation Perturbs problem; Switch on perturbation (50), automatic (100), don't try perturbing (102).\n clp: Perturbation - Default = 3; See link for more specifications.\nmaxSolutions Terminate after this many feasible solutions have been found.\n cbc: maxSolutions - Default = -1; See link for more specifications.\nmaxNodes Terminate after this many branch-and-bound nodes have been evaluated\n cbc: maxNodes - Default = -1; See link for more specifications.\nallowableGap Terminate after optimality gap is less than this value (on an absolute scale)\n cbc: allowableGap - Default = -1; See link for more specifications.\nratioGap Terminate after optimality gap is smaller than this relative fraction.\n cbc: ratioGap - Default = Inf; See link for more specifications.\nthreads Set the number of threads to use for parallel branch & bound.\n cbc: threads - Default = 1; See link for more specifications.","category":"page"},{"location":"Model_Reference/mga/#Modeling-to-Generate-Alternatives","page":"Modeling to Generate Alternatives","title":"Modeling to Generate Alternatives","text":"","category":"section"},{"location":"Model_Reference/mga/","page":"Modeling to Generate Alternatives","title":"Modeling to Generate Alternatives","text":"Modules = [GenX]\nPages = [\"modeling_to_generate_alternatives.jl\"]","category":"page"},{"location":"Model_Reference/mga/#GenX.mga-Tuple{JuMP.Model, AbstractString, Dict, Dict}","page":"Modeling to Generate Alternatives","title":"GenX.mga","text":"mga(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nWe have implemented an updated Modeling to Generate Alternatives (MGA) Algorithm proposed by Berntsen and Trutnevyte (2017) to generate a set of feasible, near cost-optimal technology portfolios. This algorithm was developed by Brill Jr, E. D., 1979 and introduced to energy system planning by DeCarolia, J. F., 2011.\n\nTo create the MGA formulation, we replace the cost-minimizing objective function of GenX with a new objective function that creates multiple generation portfolios by zone. We further add a new budget constraint based on the optimal objective function value f^* of the least-cost model and the user-specified value of slack delta. After adding the slack constraint, the resulting MGA formulation is given as:\n\nbeginaligned\n\ttextmaxmin quad\n\tsum_z in mathcalZsum_r in mathcalR beta_zr^kP_zr\n\ttextst quad\n\tP_zr = sum_y in mathcalGsum_t in mathcalT omega_t Theta_ytzr \n\t f leq f^* + delta \n\tAx = b\nendaligned\n\nwhere, beta_zr is a random objective fucntion coefficient betwen 0100 for MGA iteration k. Theta_ytzr is a generation of technology y in zone z in time period t that belongs to a resource type r. We aggregate Theta_ytzr into a new variable P_zr that represents total generation from technology type r in a zone z. In the second constraint above, delta denote the increase in budget from the least-cost solution and f represents the expression for the total system cost. The constraint Ax = b represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.\n\n\n\n\n\n","category":"method"},{"location":"User_Guide/running_model/#Running-the-model","page":"Running the Model","title":"Running the model","text":"","category":"section"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"When running a new case, it is recommended to create a new folder for the case outside of the GenX repository. This folder should contain all the .csv input files described in the GenX Inputs section, as well as the settings folder containing at least the genx_settings.yml and [solver_name].yml files. ","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"tip: Tip\nCheck out the Running GenX for additional information on how to run GenX and what happens when you run a case.","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"Once the model and the solver are set up, and once all the .csv input files are ready, GenX can be run using the following command:","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"$ julia --project=/path/to/GenX\n\njulia> using GenX\njulia> run_genx_case!(\"/path/to/case\")","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case. ","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"Alternatively, you can create a Run.jl file with the following code:","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"using GenX\nrun_genx_case!(dirname(@__FILE__))","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"and and place it in the case folder. Then, you can run the case by opening a terminal and running the following command:","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"$ julia --project=\"/path/to/GenX\" /path/to/case/Run.jl","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case.","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"The output files will be saved in the Results folder inside the case folder. Check out the GenX Outputs section for more information on the output files.","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"note: Slack Variables\nTo run a case with slack variables, check out the Policy Slack Variables section.","category":"page"},{"location":"Model_Reference/Resources/long_duration_storage/#Long-Duration-Storage","page":"Long Duration Storage","title":"Long Duration Storage","text":"","category":"section"},{"location":"Model_Reference/Resources/long_duration_storage/","page":"Long Duration Storage","title":"Long Duration Storage","text":"Modules = [GenX]\nPages = [\"long_duration_storage.jl\"]","category":"page"},{"location":"Model_Reference/Resources/long_duration_storage/#GenX.long_duration_storage!-Tuple{JuMP.Model, Dict, Dict}","page":"Long Duration Storage","title":"GenX.long_duration_storage!","text":"long_duration_storage!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates variables and constraints enabling modeling of long duration storage resources when modeling representative time periods.\n Storage inventory balance at beginning of each representative period The constraints in this section are used to approximate the behavior of long-duration energy storage technologies when approximating annual grid operations by modeling operations over representative periods. Previously, the state of charge balance for storage (as defined in storage_all()) assumed that state of charge at the beginning and end of each representative period has to be the same. In other words, the amount of energy built up or consumed by storage technology o in zone z over the representative period m, Delta Q_ozm = 0. This assumption implicitly excludes the possibility of transferring energy from one representative period to the other which could be cost-optimal when the capital cost of energy storage capacity is relatively small. To model long-duration energy storage using representative periods, we replace the state of charge equation, such that the first term on the right hand side accounts for change in storage inventory associated with representative period m (Delta Q_ozm), which could be positive (net accumulation) or negative (net reduction).\n\nbeginaligned\n Gamma_oz(m-1)times tau^period+1 =left(1-eta_oz^lossright)times left(Gamma_ozmtimes tau^period -Delta Q_ozmright) - \n frac1eta_oz^dischargeTheta_oz(m-1)times tau^period+1 + eta_oz^chargePi_oz(m-1)times tau^period+1 quad forall o in mathcalO^LDES z in mathcalZ m in mathcalM\nendaligned\n\nBy definition mathcalT^start=left(m-1right) times tau^period+1 m in mathcalM, which implies that this constraint is defined for all values of t in T^start. \nStorage inventory change input periods We need additional variables and constraints to approximate energy exchange between representative periods, while accounting for their chronological occurence in the original input time series data and the possibility that two representative periods may not be adjacent to each other (see Figure below). To implement this, we introduce a new variable Q_oz n that models inventory of storage technology o in O in zone z in each input period n in mathcalN. Additionally we define a function mapping, f n rightarrow m, that uniquely maps each input period n to its corresponding representative period m. This mapping is available as an output of the process used to identify representative periods (E.g. k-means clustering Mallapragada et al., 2018).\n\n(Image: Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations) Figure. Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations\n\nThe following two equations define the storage inventory at the beginning of each input period n+1 as the sum of storage inventory at begining of previous input period n plus change in storage inventory for that period. The latter is approximated by the change in storage inventory in the corresponding representative period, identified per the mapping f(n). If the input period is also a representative period, then a second constraint enforces that initial storage level estimated by the intra-period storage balance constraint should equal the initial storage level estimated from the inter-period storage balance constraints.\n\nbeginaligned\n Q_ozn+1 = Q_ozn + Delta Q_ozf(n)\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalN\nendaligned\n\nbeginaligned\n Q_ozn =Gamma_ozf(n)times tau^period - Delta Q_ozm\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalN^rep\nendaligned\n\nFinally, the next constraint enforces that the initial storage level for each input period n must be less than the installed energy capacity limit. This constraint ensures that installed energy storage capacity is consistent with the state of charge during both the operational time periods t during each sample period m as well as at the start of each chronologically ordered input period n in the full annual time series.\n\nbeginaligned\n Q_ozn leq Delta^total energy_oz\nquad forall n in mathcalN o in mathcalO^LDES\nendaligned\n\nIf the capacity reserve margin constraint is enabled, a similar set of constraints is used to track the evolution of the energy held in reserve across representative periods. The main linking constraint is as follows:\n\nbeginaligned\n Gamma^CRM_oz(m-1)times tau^period+1 =left(1-eta_oz^lossright)times left(Gamma^CRM_ozmtimes tau^period -Delta Q_ozmright) + \n frac1eta_oz^dischargeTheta^CRM_oz(m-1)times tau^period+1 - eta_oz^chargePi^CRM_oz(m-1)times tau^period+1 quad forall o in mathcalO^LDES z in mathcalZ m in mathcalM\nendaligned\n\nAll other constraints are identical to those used to track the actual state of charge, except with the new variables Q^CRM_ozn and Delta Q^CRM_ozn used in place of Q_ozn and Delta Q_ozn, respectively.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/retrofit/#Retrofit","page":"Retrofit","title":"Retrofit","text":"","category":"section"},{"location":"Model_Reference/Resources/retrofit/","page":"Retrofit","title":"Retrofit","text":"Modules = [GenX]\nPages = [\"retrofits.jl\"]","category":"page"},{"location":"Model_Reference/Resources/retrofit/#GenX.retrofit-Tuple{JuMP.Model, Dict}","page":"Retrofit","title":"GenX.retrofit","text":"retrofit(EP::Model, inputs::Dict)\n\nThis function defines the constraints for operation of retrofit technologies, including \t\tbut not limited to carbon capture and thermal energy storage.\n\nFor retrofittable source technologies y and retrofit technologies r in the same region z and retrofit cluster id, (i.e. y in RS(id) and r in RO(id)), the total retrofit capacity Omega_r that may be installed is constrained by the available retrofittable capacity P_y as well as the efficiency ef_r of the retrofit technology.\n\nbeginaligned\n sum_y in RS(id)P_y = sum_r in RO(id)fracOmega_ref_r quad quad quad quad forall id in RETROFIT\nendaligned\n\nwhere RETROFIT represents the set of all retrofit IDs (clusters) in the model.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/generate_model/#Generating-the-model","page":"Generate the Model","title":"Generating the model","text":"","category":"section"},{"location":"Model_Reference/generate_model/","page":"Generate the Model","title":"Generate the Model","text":"Modules = [GenX]\nPages = [\"generate_model.jl\"]","category":"page"},{"location":"Model_Reference/generate_model/#GenX.generate_model-Tuple{Dict, Dict, MathOptInterface.OptimizerWithAttributes}","page":"Generate the Model","title":"GenX.generate_model","text":"generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAttributes,modeloutput = nothing)\n\nThis function sets up and solves a constrained optimization model of electricity system capacity expansion and operation problem and extracts solution variables for later processing.\n\nIn addition to calling a number of other modules to create constraints for specific resources, policies, and transmission assets, this function initializes two key expressions that are successively expanded in each of the resource-specific modules: (1) the objective function; and (2) the zonal power balance expression. These two expressions are the only expressions which link together individual modules (e.g. resources, transmission assets, policies), which otherwise are self-contained in defining relevant variables, expressions, and constraints.\n\nObjective Function\n\nThe objective function of GenX minimizes total annual electricity system costs over the following six components shown in the equation below:\n\nbeginaligned\n\tsum_y in mathcalG sum_z in mathcalZ\n\tleft( (pi^INVEST_yz times overlineOmega^size_yz times Omega_yz)\n\t+ (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right) + notag \n\tsum_y in mathcalO sum_z in mathcalZ\n\tleft( (pi^INVESTenergy_yz times Omega^energy_yz)\n\t+ (pi^FOMenergy_yz times Delta^totalenergy_yz)right) + notag \n\tsum_y in mathcalO^asym sum_z in mathcalZ\n\tleft( (pi^INVESTcharge_yz times Omega^charge_yz)\n\t+ (pi^FOMcharge_yz times Delta^totalcharge_yz)right) + notag \n\t sum_y in mathcalG sum_z in mathcalZ sum_t in mathcalT left( omega_ttimes(pi^VOM_yz + pi^FUEL_yz)times Theta_yztright) + sum_y in mathcalO cup DF sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMcharge_yz times Pi_yztright) +notag \n\tsum_s in mathcalS sum_z in mathcalZ sum_t in mathcalTleft(omega_t times n_s^slope times Lambda_sztright) + sum_t in mathcalT left(omega_t times pi^unmet_rsv times r^unmet_tright) notag \n\tsum_y in mathcalH sum_z in mathcalZ sum_t in mathcalTleft(omega_t times pi^START_yz times chi_sztright) + notag \n\t sum_l in mathcalLleft(pi^TCAP_l times bigtriangleupvarphi^max_lright)\nendaligned\n\nThe first summation represents the fixed costs of generation/discharge over all zones and technologies, which refects the sum of the annualized capital cost, pi^INVEST_yz, times the total new capacity added (if any), plus the Fixed O&M cost, pi^FOM_yz, times the net installed generation capacity, overlineOmega^size_yz times Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources. This term includes the sum of the annualized energy capital cost, pi^INVESTenergy_yz, times the total new energy capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed energy storage capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components (mathcalO^asym). This term includes the sum of the annualized charging power capital cost, pi^INVESTcharge_yz, times the total new charging power capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed charging power capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe fourth and fifth summations corresponds to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, pi^FUEL_yz (if any), plus variable O&M cost, pi^VOM_yz times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, yinmathcalDF) in time step t, Theta_yzt, and the weight of each time step t, omega_t, where omega_t is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, t such that the sum of omega_t forall t in T = 8760, approximating annual operating costs. The fifth summation represents the variable charging O&M cost, pi^VOMcharge_yz times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step t , Pi_yzt and the annual weight of time step t,omega_t.\n\nThe sixth summation represents the total cost of unserved demand across all segments s of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), n_s^slope, times the amount of non-served energy, Lambda_yzt, for each segment on each zone during each time step (weighted by omega_t).\n\nThe seventh summation represents the total cost of not meeting hourly operating reserve requirements, where pi^unmet_rsv is the cost penalty per unit of non-served reserve requirement, and r^unmet_t is the amount of non-served reserve requirement in each time step (weighted by omega_t).\n\nThe eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. y in mathcalUC), equal to the cost of start-up, pi^START_yz, times the number of startup events, chi_yzt, for the cluster of units in each zone and time step (weighted by omega_t).\n\nThe last term corresponds to the transmission reinforcement or construction costs, for each transmission line in the model. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, pi^TCAP_l, times the additional transmission capacity variable, bigtriangleupvarphi^max_l. Note that fixed O\\&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.\n\nIn summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions: (1) where and how to invest on capacity, (2) how to dispatch or operate that capacity, (3) which consumer demand segments to serve or curtail, (4) how to cycle and commit thermal units subject to unit commitment decisions, (5) and where and how to invest in additional transmission network capacity to increase power transfer capacity between zones. Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.\n\nPower Balance\n\nThe power balance constraint of the model ensures that electricity demand is met at every time step in each zone. As shown in the constraint, electricity demand, D_tz, at each time step and for each zone must be strictly equal to the sum of generation, Theta_yzt, from thermal technologies (mathcalH), curtailable VRE (mathcalVRE), must-run resources (mathcalMR), and hydro resources (mathcalW). At the same time, energy storage devices (mathcalO) can discharge energy, Theta_yzt to help satisfy demand, while when these devices are charging, Pi_yzt, they increase demand. For the case of flexible demand resources (mathcalDF), delaying demand (equivalent to charging virtual storage), Pi_yzt, decreases demand while satisfying delayed demand (equivalent to discharging virtual demand), Theta_yzt, increases demand. Price-responsive demand curtailment, Lambda_szt, also reduces demand. Finally, power flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign in the below constraint. At the same time losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see Transmission section).\n\nbeginaligned\n\t sum_yin mathcalHTheta_yzt +sum_yin mathcalVRETheta_yzt +sum_yin mathcalMRTheta_yzt + sum_yin mathcalO(Theta_yzt-Pi_yzt) + notag\n\t sum_yin mathcalDF(-Theta_yzt+Pi_yzt) +sum_yin mathcalWTheta_yzt+ notag\n\t+ sum_sin mathcalSLambda_szt - sum_lin mathcalL(varphi^map_lz times Phi_lt) -frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot)) = D_zt\n\tforall zin mathcalZ t in mathcalT\nendaligned\n\nArguments\n\nsetup::Dict: Dictionary containing the settings for the model.\ninputs::Dict: Dictionary containing the inputs for the model.\nOPTIMIZER::MOI.OptimizerWithAttributes: The optimizer to use for solving the model.\n\nReturns\n\nModel: The model object containing the entire optimization problem model to be solved by solve_model.jl\n\n\n\n\n\n","category":"method"},{"location":"Model_Concept_Overview/model_introduction/#GenX-Model-Introduction","page":"Model Introduction","title":"GenX Model Introduction","text":"","category":"section"},{"location":"Model_Concept_Overview/model_introduction/#Introduction","page":"Model Introduction","title":"Introduction","text":"","category":"section"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"GenX allows for the simultaneous co-optimization of several interlinked power system decision layers, described below:","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Capacity expansion planning (e.g., investment and retirement decisions for a full range of centralized and distributed generation, storage, and demand-side resources)\nHourly dispatch of generation, storage, and demand-side resources,\nUnit commitment decisions and operational constraints for thermal generators,\nCommitment of generation, storage, and demand-side capacity to meet system operating reserves requirements,\nCommitment of generation, storage, and demand-side capacity to meet capacity reserve requirements,\nTransmission network power flows (including losses) and network expansion decisions, and\nSeveral optional policy constraints","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Depending on the dimensionality of the problem, it may not be possible to model all decision layers at the highest possible resolution of detail, so the GenX model is designed to be highly configurable, allowing the user to specify the level of detail or abstraction along each of these layers or to omit one or more layers from consideration entirely.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"For example, while investment and dispatch decisions (Layers 1 and 2) are a consistent feature of the model under all configurations, the user has several options with regards to representing the operational constraints on various thermal power plants (e.g., coal, gas, nuclear, and biomass generators). Unit commitment (e.g., start-up and shut-down) decisions Morales-España et al., 2013 (Layer 3) can be modeled at the individual power plant level (as per De Sisternes Jimenez, 2014); by using an efficient clustering of similar or identical units (as per Palmintier, 2011, Palmintier, 2013, Palmintier, 2014); by using a linear relaxation (or convex hull) of the integer unit commitment constraints set; or ignoring unit commitment decisions entirely and treating generator output as fully continuous. Furthermore, different levels of resolution can be selected for each individual resource type, as desired (e.g., larger thermal units can be represented with integer unit commitment decisions while smaller units can be treated as fully continuous). In such a manner, the model can be configured to represent operating constraints on thermal generators at a level of resolution that achieves a desired balance between abstraction error and computational tractability and provides sufficient accuracy to generate insights for the problem at hand.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"The model can also be configured to consider commitment of capacity to supply frequency regulation (symmetric up and down) and operating reserves (up) needed by system operators to robustly resolve short-term uncertainty in demand and renewable energy forecasts and power plant or transmission network failures (Layer 4). Alternatively, reserve commitments can be ignored if desired.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Additionally, the model can approximate resource adequacy requirements through capacity reserve margin requirements at the zonal and/or system level (Layer 5). In this way, the model can approximate varying structure of capacity markets seen in deregulated electricity markets in the U.S. and other regions.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"The model also allows for transmission networks to be represented at several levels of detail (Layer 6) including at a zonal level with transport constraints on power flows between zones (as per Mai et al., 2013, Johnston et al., 2013, Hirth, 2017); or as a single zone problem where transmission constraints and flows are ignored. (A DC optimal power flow formulation is in development.) In cases where a nodal or zonal transmission model is employed, network capacity expansion decisions can be modeled or ignored, and transmission losses can be represented either as a linear function of power flows or a piecewise linear approximation of a quadratic function of power flows between nodes or zones (as per Zhang et al., 2013, Fitiwi et al., 2016), with the number of segments in the piecewise approximation specified by the user as desired. In a multi-zonal or nodal configuration, GenX can therefore consider siting generators in different locations, including balancing tradeoffs between access to different renewable resource quality, siting restrictions, and impacts on network congestions, power flows and losses.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"GenX also allows the user to specify several optional public policy constraints, such as CO2 emissions limits, minimum energy share requirements (such as renewable portfolio standard or clean energy standard policies), and minimum technology capacity requirements (e.g. technology deployment mandates).","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Finally, the model is usually configured to consider a full year of operating decisions at an hourly resolution, but as this is often not tractable when considering large-scale problems with high resolution in other dimensions, GenX is also designed to model a number of subperiods – typically multiday periods of chronologically sequential hourly operating decisions – that can be selected via appropriate statistical clustering methods to represent a full year of operations (De Sisternes Jimenez and Webster, 2013, De Sisternes Jimenez, 2014, Poncelet et al., 2016, Nahmmacher et al., 2016, Blanford et al., 2016, Merrick, 2016, Mallapragada et al., 2018). GenX ships with a built-in time-domain reduction package that uses k-means or k-medoids to cluster raw time series data for demand (load) profiles and resource capacity factor profiles into representative periods during the input processing stage of the model. This method can also consider extreme points in the time series to capture noteworthy periods or periods with notably poor fits.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"With appropriate configuration of the model, GenX thus allows the user to tractably consider several interlinking decision layers in a single, monolithic optimization problem that would otherwise have been necessary to solve in different separated stages or models. The following figure reflects the range of configurations currently possible along the three key dimensions of chronological detail, operational detail, and network detail.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"(Image: Range of configurations currently implemented in GenX along three key dimensions of model resolution) Figure. Range of configurations currently implemented in GenX along three key dimensions of model resolution","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"The model can be configured to consider a single future planning year or multiple planning stages (or investment periods) in sequence. ","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"In single-stage planning mode, the model formulation is static, in the sense that its objective is not to determine when investments should take place over time, but rather to produce a snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions. \nThe user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here. \nThe user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as \"myopic\" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"More information on the two sequential, multi-stage planning modes can be found in the section on Multi-stage under the Model function reference tab. ","category":"page"},{"location":"Model_Concept_Overview/model_introduction/#Uses","page":"Model Introduction","title":"Uses","text":"","category":"section"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Tutorial-4:-Model-Generation","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"To run GenX, we use the file Run.jl. This file will solve the optimization problem and generate the output files as described in the documentation and previous tutorial. It does so by first generating the model, then solving the model, both according to settings described in genx_settings.yml. However, Run.jl only contains one commmand, run_genx_case!(dirname(@__FILE__)). This can be confusing for users viewing the files for the first time. In reality, this function signals many more functions to run, generating and solving the model. This tutorial explains how the model in GenX is generated. The next tutorial will then describe how it is solved.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"We'll start by explaining JuMP, the optimization package that GenX uses to generate and solve the model.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Table-of-Contents","page":"Tutorial 4: Model Generation","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"JuMP\nGenerate Model\nArguments\nRun generate_model","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"JuMP is a modeling language for Julia. It allows users to create models for optimization problems, define variables and constraints, and apply a variety of solvers for the model. ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"GenX is a Linear Program (LP), which is a form of optimization problem in which a linear objective is minimized (or maximized) according to a set of linear constraints. For more information on LPs, see Wikipedia.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"using JuMP\nusing HiGHS","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Let's say we want to build a power grid consisting of and coal and wind plants. We want to decrease the cost of producing energy while still meeting a certain emissions threshold and full grid demand. Coal plants are cheaper to build and run but have higher emissions than wind farms. To find the minimum cost of a power grid meeting these constraints, we construct an LP using JuMP.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"beginaligned\n min 10 x + 15 y textObjective function (cost) \n textst \n x + y geq 10 textGrid Demand\n 55x + 70y leq 1000 textConstruction constraint\n 40 x + 5 y leq 200 textEmissions constraint \n x y geq 0 textNon-negativity constraints\nendaligned","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The core of the JuMP model is the function Model(), which creates the structure of our LP. Model() takes an optimizer as its input.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"power = Model(HiGHS.Optimizer)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"A JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: EMPTY_OPTIMIZER\nSolver name: HiGHS","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The model needs variables, defined using the JuMP function @variable:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@variable(power,x) # Coal\n@variable(power,y) # Wind","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Using the JuMP function @constraint, we can add the constraints of the model:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@constraint(power, non_neg_x, x >= 0) # Non-negativity constraint (can't have negative power plants!)\n@constraint(power, non_neg_y, y >= 0) # Non-negativity constraint\n\n@constraint(power, emissions, 40x + 5y <= 200) # Emisisons constraint\n@constraint(power, construction_costs, 55x + 70y <= 1000) # Cost of constructing a new plant\n\n@constraint(power, demand, x + y >= 10) # Grid demand","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"x + y geq 10","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Next, the function @expression defines an expression that can be used in either a constraint or objective function. In GenX, expressions are defined throughout the model generation and put into constraints and the objective function later.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@expression(power,objective,10x+15y)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"$ 10 x + 15 y $","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Finally, we define the objective function itself:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@objective(power, Min, objective)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"10 x + 15 y","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Our model is now set up! ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"print(power)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"beginaligned\nminquad 10 x + 15 y\ntextSubject to quad x geq 0\n y geq 0\n x + y geq 10\n 40 x + 5 y leq 200\n 55 x + 70 y leq 1000\nendaligned ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"In the next Tutorial, we go over how to use JuMP to solve the model we've constructed.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"When Run.jl is called, the model for GenX is constructed in a similar way, but with many more factors to consider. The next section goes over how the GenX model is constructed before it is solved.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Generate-Model","page":"Tutorial 4: Model Generation","title":"Generate Model","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The basic structure of the way Run.jl generates and solves the model is as follows:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The function run_genx_case(case) takes the \"case\" as its input. The case is all of the input files and settings found in the same folder as Run.jl. For example, in example_systems/1_three_zones, the case is:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Run_genx_case defines the setup, which are the settings in genx_settings.yml. From there, either run_genx_case_simple(case, mysetup) orrun_genx_case_multistage(case, mysetup) is called. Both of these define the inputs and optimizer. The optimizer is the solver as specified in genx_settings.yml, and the inputs are a variety of parameters specified by the settings and csv files found in the folder. Both of these functions then call generate_model(mysetup, myinputs, OPTIMIZER), which is the main subject of this tutorial.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"As in the above example, generate_model utilizes the JuMP functions Model(), @expression, @variable, and @constraints to form a model. This section goes through generate_model and explains how the expressions are formed to create the model.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Arguments","page":"Tutorial 4: Model Generation","title":"Arguments","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Generate_model takes three arguments: setup, inputs, and optimizer:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"To generate the arguments, we have to set a case path (this is set automatically when Run.jl is called):","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"using GenX","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"case = joinpath(\"example_systems/1_three_zones\") ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" \"example_systems/1_three_zones\"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Setup includes the settings from genx_settings.yml along with the default settings found in configure_settings.jl. The function configure_settings combines the two.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"genx_settings = GenX.get_settings_path(case, \"genx_settings.yml\") # Settings YAML file path\nwriteoutput_settings = GenX.get_settings_path(case, \"output_settings.yml\") # Set output path\nsetup = GenX.configure_settings(genx_settings,writeoutput_settings) # Combines genx_settings with defaults","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Configuring Settings\n Dict{Any, Any} with 24 entries:\n \"NetworkExpansion\" => 0\n \"TimeDomainReductionFolder\" => \"TDR_Results\"\n \"EnableJuMPStringNames\" => false\n \"Trans_Loss_Segments\" => 1\n \"ModelingtoGenerateAlternativeSlack\" => 0.1\n \"Solver\" => \"HiGHS\"\n \"Reserves\" => 0\n \"MultiStage\" => 0\n \"OverwriteResults\" => 0\n \"ModelingToGenerateAlternatives\" => 0\n \"MaxCapReq\" => 1\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1\n \"ModelingToGenerateAlternativeIterations\" => 3\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 1\n \"PrintModel\" => 0\n \"TimeDomainReduction\" => 1\n \"CapacityReserveMargin\" => 1\n \"MethodofMorris\" => 0\n \"StorageLosses\" => 1\n \"IncludeLossesInESR\" => 0\n \"UCommit\" => 2","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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. As a reminder, TDR_results is not overwritten when called again. The cell below will delete a preexisting TDR_results folder if it is there.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"TDRpath = joinpath(case, setup[\"TimeDomainReductionFolder\"])\nsystem_path = joinpath(case, setup[\"SystemFolder\"])\n\nsettings_path = GenX.get_settings_path(case)\n\nif \"TDR_results\" in cd(readdir,case)\n rm(joinpath(case,\"TDR_results\"), recursive=true) \nend\n\nif setup[\"TimeDomainReduction\"] == 1\n GenX.prevent_doubled_timedomainreduction(system_path)\n if !GenX.time_domain_reduced_files_exist(TDRpath)\n println(\"Clustering Time Series Data (Grouped)...\")\n GenX.cluster_inputs(case, settings_path, setup)\n else\n println(\"Time Series Data Already Clustered.\")\n end\nend","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Clustering Time Series Data (Grouped)...\n Reading Input CSV Files\n Network.csv Successfully Read!\n Load_data.csv Successfully Read!\n Fuels_data.csv Successfully Read!\n Generators_data.csv Successfully Read!\n Generators_variability.csv Successfully Read!\n Validating time basis\n Capacity_reserve_margin.csv Successfully Read!\n Minimum_capacity_requirement.csv Successfully Read!\n Maximum_capacity_requirement.csv Successfully Read!\n Energy_share_requirement.csv Successfully Read!\n CO2_cap.csv Successfully Read!\n CSV Files Successfully Read In From Example_Systems_Tutorials/SmallNewEngland/OneZone\n\n Dict{String, Any} with 9 entries:\n \"RMSE\" => Dict(\"Load_MW_z1\"=>1100.54, \"NG\"=>0.312319, \"onshore_wind_…\n \"OutputDF\" => DataFrame…\n \"ColToZoneMap\" => Dict(\"Load_MW_z1\"=>1, \"battery_z1\"=>1, \"natural_gas_combin…\n \"ClusterObject\" => KmeansResult{Matrix{Float64}, Float64, Int64}([-1.38728 -1…\n \"TDRsetup\" => Dict{Any, Any}(\"IterativelyAddPeriods\"=>1, \"ExtremePeriods…\n \"Assignments\" => [1, 1, 1, 1, 2, 2, 2, 2, 2, 3 … 6, 4, 3, 5, 5, 9, 10, 10…\n \"InputDF\" => [672×49 DataFrame\n \"Weights\" => [673.846, 1010.77, 673.846, 842.308, 842.308, 1853.08, 185…\n \"Centers\" => Any[1, 7, 12, 15, 23, 24, 28, 29, 48, 50, 51]","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The optimizer argument is taken from setup:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"OPTIMIZER = GenX.configure_solver(settings_path,HiGHS.Optimizer)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The function configure_solver converts the string from \"Solver\" to a MathOptInterface optimizer so it can be used in the JuMP model as the optimizer. It also goes into the settings file for the specified solver (in this case HiGHS, so 1_three_zones/settings/highs_settings.yml) and uses the settings to configure the solver to be used later.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"typeof(OPTIMIZER)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" MathOptInterface.OptimizerWithAttributes","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The \"inputs\" argument is generated by the function load_inputs from the case in run_genx_case_simple (or multistage). If TDR is set to 1 in the settings file, then load_inputs will draw some of the files from the TDR_Results folder. TDR_Results is produced when the case is run. ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"inputs = GenX.load_inputs(setup, case)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Reading Input CSV Files\n Network.csv Successfully Read!\n Load_data.csv Successfully Read!\n Fuels_data.csv Successfully Read!\n Generators_data.csv Successfully Read!\n Generators_variability.csv Successfully Read!\n Validating time basis\n Capacity_reserve_margin.csv Successfully Read!\n Minimum_capacity_requirement.csv Successfully Read!\n Maximum_capacity_requirement.csv Successfully Read!\n Energy_share_requirement.csv Successfully Read!\n CO2_cap.csv Successfully Read!\n CSV Files Successfully Read In From Example_Systems_Tutorials/SmallNewEngland/OneZone\n\n Dict{Any, Any} with 66 entries:\n \"Z\" => 1\n \"LOSS_LINES\" => [1]\n \"RET_CAP_CHARGE\" => Int64[]\n \"pC_D_Curtail\" => [50.0]\n \"dfGen\" => [4×68 DataFram\n \"pTrans_Max_Possible\" => [2.95]\n \"pNet_Map\" => [1.0;;]\n \"omega\" => [4.01099, 4.01099, 4.01099, 4.01099, 4.01099, 4.0109…\n \"RET_CAP_ENERGY\" => [4]\n \"RESOURCES\" => String31[\"natural_gas_combined_cycle\", \"solar_pv\", \"…\n \"COMMIT\" => [1]\n \"pMax_D_Curtail\" => [1]\n \"STOR_ALL\" => [4]\n \"THERM_ALL\" => [1]\n \"dfCO2CapZones\" => [1;;]\n \"REP_PERIOD\" => 11\n \"MinCapReq\" => [5.0, 10.0, 6.0]\n \"STOR_LONG_DURATION\" => Int64[]\n \"dfCapRes\" => [0.156;;]\n \"STOR_SYMMETRIC\" => [4]\n \"VRE\" => [2, 3]\n \"RETRO\" => Int64[]\n \"THERM_COMMIT\" => [1]\n \"TRANS_LOSS_SEGS\" => 1\n \"H\" => 168\n ⋮ => ⋮","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Now that we have our arguments, we're ready to generate the model itself.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Run-generate_model","page":"Tutorial 4: Model Generation","title":"Run generate_model","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"This subsection replicates the arguments in the function generate_model. Note: Running some of these cells for a second time will throw an error as the code will attempt to define a new expression with the name of an existing expression. To run the Tutorial again, clear and restart the kernel.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"First, we initialize a model and define the time step and zone variables","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"EP = Model(OPTIMIZER) # From JuMP","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"A JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: EMPTY_OPTIMIZER\nSolver name: HiGHS","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"T = inputs[\"T\"]; # Number of time steps (hours)\nZ = inputs[\"Z\"]; # Number of zones","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Next, the dummy variable vZERO, the objective function, the power balance expression, and zone generation expression are all initialized to zero:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Introduce dummy variable fixed to zero to ensure that expressions like eTotalCap,\n# eTotalCapCharge, eTotalCapEnergy and eAvail_Trans_Cap all have a JuMP variable\n\nGenX.set_string_names_on_creation(EP, Bool(setup[\"EnableJuMPStringNames\"]))\n@variable(EP, vZERO == 0);\n\n# Initialize Power Balance Expression\n# Expression for \"baseline\" power balance constraint\nGenX.create_empty_expression!(EP, :ePowerBalance, (T, Z))\n\n# Initialize Objective Function Expression\nEP[:eObj] = AffExpr(0.0)\n\nGenX.create_empty_expression!(EP, :eGenerationByZone, (Z, T))\n\n# Energy losses related to technologies\nGenX.create_empty_expression!(EP, :eELOSSByZone, Z)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" 1×1848 Matrix{Int64}:\n 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","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Initialize Capacity Reserve Margin Expression\nif setup[\"CapacityReserveMargin\"] > 0\n GenX.create_empty_expression!(EP, :eCapResMarBalance, (inputs[\"NCapacityReserveMargin\"], T))\nend\n\n# Energy Share Requirement\nif setup[\"EnergyShareRequirement\"] >= 1\n GenX.create_empty_expression!(EP, :eESR, inputs[\"nESR\"])\nend\n\nif setup[\"MinCapReq\"] == 1\n GenX.create_empty_expression!(EP, :eMinCapRes, inputs[\"NumberOfMinCapReqs\"])\nend\n\nif setup[\"MaxCapReq\"] == 1\n GenX.create_empty_expression!(EP, :eMaxCapRes, inputs[\"NumberOfMaxCapReqs\"])\nend","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The other settings will be used later on.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Infrastructure\nGenX.discharge!(EP, inputs, setup)\n\nGenX.non_served_energy!(EP, inputs, setup)\n\nGenX.investment_discharge!(EP, inputs, setup)\n\nif setup[\"UCommit\"] > 0\n GenX.ucommit!(EP, inputs, setup)\nend\n\nGenX.fuel!(EP, inputs, setup)\n\nGenX.co2!(EP, inputs) \n\nif setup[\"OperationalReserves\"] > 0\n GenX.operational_reserves!(EP, inputs, setup)\nend\n\nif Z > 1\n GenX.investment_transmission!(EP, inputs, setup)\n GenX.transmission!(EP, inputs, setup)\nend\n\nif Z > 1 && setup[\"DC_OPF\"] != 0\n GenX.dcopf_transmission!(EP, inputs, setup)\nend","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Fuel Module\n CO2 Module\n Investment Transmission Module\n Transmission Module","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Technologies\n# Model constraints, variables, expression related to dispatchable renewable resources\n\nif !isempty(inputs[\"VRE\"])\n GenX.curtailable_variable_renewable!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to non-dispatchable renewable resources\nif !isempty(inputs[\"MUST_RUN\"])\n GenX/must_run!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to energy storage modeling\nif !isempty(inputs[\"STOR_ALL\"])\n GenX.storage!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to reservoir hydropower resources\nif !isempty(inputs[\"HYDRO_RES\"])\n GenX.hydro_res!(EP, inputs, setup)\nend\n\nif !isempty(inputs[\"ELECTROLYZER\"])\n GenX.electrolyzer!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to reservoir hydropower resources with long duration storage\nif inputs[\"REP_PERIOD\"] > 1 && !isempty(inputs[\"STOR_HYDRO_LONG_DURATION\"])\n GenX.hydro_inter_period_linkage!(EP, inputs)\nend\n\n# Model constraints, variables, expression related to demand flexibility resources\nif !isempty(inputs[\"FLEX\"])\n GenX.flexible_demand!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to thermal resource technologies\nif !isempty(inputs[\"THERM_ALL\"])\n GenX.thermal!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expressions related to the co-located VRE-storage resources\nif !isempty(inputs[\"VRE_STOR\"])\n GenX.vre_stor!(EP, inputs, setup)\nend\n\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Finally, we define expressions and variables using policies outlined in the inputs. These functions can be found in src/policies and in the Emission mitigation policies section of the documentation:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Policies\n\nif setup[\"OperationalReserves\"] > 0\n GenX.operational_reserves_constraints!(EP, inputs)\nend\n\n# CO2 emissions limits\nif setup[\"CO2Cap\"] > 0\n GenX.co2_cap!(EP, inputs, setup)\nend\n\n# Endogenous Retirements\nif setup[\"MultiStage\"] > 0\n GenX.endogenous_retirement!(EP, inputs, setup)\nend\n\n# Energy Share Requirement\nif setup[\"EnergyShareRequirement\"] >= 1\n GenX.energy_share_requirement!(EP, inputs, setup)\nend\n\n#Capacity Reserve Margin\nif setup[\"CapacityReserveMargin\"] > 0\n GenX.cap_reserve_margin!(EP, inputs, setup)\nend\n\nif (setup[\"MinCapReq\"] == 1)\n GenX.minimum_capacity_requirement!(EP, inputs, setup)\nend\n\nif setup[\"MaxCapReq\"] == 1\n GenX.maximum_capacity_requirement!(EP, inputs, setup)\nend\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n 3-element Vector{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}, ScalarShape}}:\n cZoneMaxCapReq[1] : -vRETCAP[2] + vCAP[2] ≤ 50\n cZoneMaxCapReq[2] : -vRETCAP[3] + vCAP[3] ≤ 100\n cZoneMaxCapReq[3] : -vRETCAP[4] + vCAP[4] ≤ 60\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The expressions and variables for the model have all been defined! All that's left to do is define the constraints and objective function.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The Objective Function here is to minimize ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@objective(EP,Min,EP[:eObj])","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"0.17159171428571432 vP_{1,1} + 0.0004010989010989012 vP_{3,1} + 0.0006016483516483517 vP_{4,1} + 0.17159171428571432 vP_{1,2} + 0.0004010989010989012 vP_{3,2} + 0.0006016483516483517 vP_{4,2} + 0.17159171428571432 vP_{1,3} + 0.0004010989010989012 vP_{3,3} + 0.0006016483516483517 vP_{4,3} + 0.17159171428571432 vP_{1,4} + 0.0004010989010989012 vP_{3,4} + 0.0006016483516483517 vP_{4,4} + 0.17159171428571432 vP_{1,5} + 0.0004010989010989012 vP_{3,5} + 0.0006016483516483517 vP_{4,5} + 0.17159171428571432 vP_{1,6} + 0.0004010989010989012 vP_{3,6} + 0.0006016483516483517 vP_{4,6} + 0.17159171428571432 vP_{1,7} + 0.0004010989010989012 vP_{3,7} + 0.0006016483516483517 vP_{4,7} + 0.17159171428571432 vP_{1,8} + 0.0004010989010989012 vP_{3,8} + 0.0006016483516483517 vP_{4,8} + 0.17159171428571432 vP_{1,9} + 0.0004010989010989012 vP_{3,9} + 0.0006016483516483517 vP_{4,9} + 0.17159171428571432 vP_{1,10} + 0.0004010989010989012 vP_{3,10} + 0.0006016483516483517 vP_{4,10} + [[\\ldots\\text{11038 terms omitted}\\ldots]] + 0.00015041208791208792 vCHARGE_{4,1819} + 0.00015041208791208792 vCHARGE_{4,1820} + 0.00015041208791208792 vCHARGE_{4,1821} + 0.00015041208791208792 vCHARGE_{4,1822} + 0.00015041208791208792 vCHARGE_{4,1823} + 0.00015041208791208792 vCHARGE_{4,1824} + 0.00015041208791208792 vCHARGE_{4,1825} + 0.00015041208791208792 vCHARGE_{4,1826} + 0.00015041208791208792 vCHARGE_{4,1827} + 0.00015041208791208792 vCHARGE_{4,1828} + 0.00015041208791208792 vCHARGE_{4,1829} + 0.00015041208791208792 vCHARGE_{4,1830} + 0.00015041208791208792 vCHARGE_{4,1831} + 0.00015041208791208792 vCHARGE_{4,1832} + 0.00015041208791208792 vCHARGE_{4,1833} + 0.00015041208791208792 vCHARGE_{4,1834} + 0.00015041208791208792 vCHARGE_{4,1835} + 0.00015041208791208792 vCHARGE_{4,1836} + 0.00015041208791208792 vCHARGE_{4,1837} + 0.00015041208791208792 vCHARGE_{4,1838} + 0.00015041208791208792 vCHARGE_{4,1839} + 0.00015041208791208792 vCHARGE_{4,1840} + 0.00015041208791208792 vCHARGE_{4,1841} + 0.00015041208791208792 vCHARGE_{4,1842} + 0.00015041208791208792 vCHARGE_{4,1843} + 0.00015041208791208792 vCHARGE_{4,1844} + 0.00015041208791208792 vCHARGE_{4,1845} + 0.00015041208791208792 vCHARGE_{4,1846} + 0.00015041208791208792 vCHARGE_{4,1847} + 0.00015041208791208792 vCHARGE_{4,1848} $","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Our constraint is the Power Balance, which is set here to have to meet the demand of the network. The demand is outlined in the last columns of Load_data.csv, and is set to inputs in from the load_load_data function within load_inputs, used in run_genx_case.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"## Power balance constraints\n# demand = generation + storage discharge - storage charge - demand deferral + deferred demand satisfaction - demand curtailment (NSE)\n# + incoming power flows - outgoing power flows - flow losses - charge of heat storage + generation from NACC\n@constraint(EP, cPowerBalance[t=1:T, z=1:Z], EP[:ePowerBalance][t,z] == inputs[\"pD\"][t,z])\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" 1848×1 Matrix{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}, ScalarShape}}:\n cPowerBalance[1,1] : vP[2,1] + vP[3,1] + vP[4,1] + vNSE[1,1,1] - vCHARGE[4,1] = 11.162\n cPowerBalance[2,1] : vP[2,2] + vP[3,2] + vP[4,2] + vNSE[1,2,1] - vCHARGE[4,2] = 10.556\n cPowerBalance[3,1] : vP[2,3] + vP[3,3] + vP[4,3] + vNSE[1,3,1] - vCHARGE[4,3] = 10.105\n cPowerBalance[4,1] : vP[2,4] + vP[3,4] + vP[4,4] + vNSE[1,4,1] - vCHARGE[4,4] = 9.878\n cPowerBalance[5,1] : vP[2,5] + vP[3,5] + vP[4,5] + vNSE[1,5,1] - vCHARGE[4,5] = 9.843\n cPowerBalance[6,1] : vP[2,6] + vP[3,6] + vP[4,6] + vNSE[1,6,1] - vCHARGE[4,6] = 10.017\n cPowerBalance[7,1] : vP[2,7] + vP[3,7] + vP[4,7] + vNSE[1,7,1] - vCHARGE[4,7] = 10.39\n cPowerBalance[8,1] : vP[2,8] + vP[3,8] + vP[4,8] + vNSE[1,8,1] - vCHARGE[4,8] = 10.727\n cPowerBalance[9,1] : vP[2,9] + vP[3,9] + vP[4,9] + vNSE[1,9,1] - vCHARGE[4,9] = 11.298\n cPowerBalance[10,1] : vP[2,10] + vP[3,10] + vP[4,10] + vNSE[1,10,1] - vCHARGE[4,10] = 11.859\n cPowerBalance[11,1] : vP[2,11] + vP[3,11] + vP[4,11] + vNSE[1,11,1] - vCHARGE[4,11] = 12.196\n cPowerBalance[12,1] : vP[2,12] + vP[3,12] + vP[4,12] + vNSE[1,12,1] - vCHARGE[4,12] = 12.321\n cPowerBalance[13,1] : vP[2,13] + vP[3,13] + vP[4,13] + vNSE[1,13,1] - vCHARGE[4,13] = 12.381\n ⋮\n cPowerBalance[1837,1] : vP[2,1837] + vP[3,1837] + vP[4,1837] + vNSE[1,1837,1] - vCHARGE[4,1837] = 13.911\n cPowerBalance[1838,1] : vP[2,1838] + vP[3,1838] + vP[4,1838] + vNSE[1,1838,1] - vCHARGE[4,1838] = 13.818\n cPowerBalance[1839,1] : vP[2,1839] + vP[3,1839] + vP[4,1839] + vNSE[1,1839,1] - vCHARGE[4,1839] = 13.71\n cPowerBalance[1840,1] : vP[2,1840] + vP[3,1840] + vP[4,1840] + vNSE[1,1840,1] - vCHARGE[4,1840] = 13.796\n cPowerBalance[1841,1] : vP[2,1841] + vP[3,1841] + vP[4,1841] + vNSE[1,1841,1] - vCHARGE[4,1841] = 15.038\n cPowerBalance[1842,1] : vP[2,1842] + vP[3,1842] + vP[4,1842] + vNSE[1,1842,1] - vCHARGE[4,1842] = 16.088\n cPowerBalance[1843,1] : vP[2,1843] + vP[3,1843] + vP[4,1843] + vNSE[1,1843,1] - vCHARGE[4,1843] = 16.076\n cPowerBalance[1844,1] : vP[2,1844] + vP[3,1844] + vP[4,1844] + vNSE[1,1844,1] - vCHARGE[4,1844] = 15.782\n cPowerBalance[1845,1] : vP[2,1845] + vP[3,1845] + vP[4,1845] + vNSE[1,1845,1] - vCHARGE[4,1845] = 15.392\n cPowerBalance[1846,1] : vP[2,1846] + vP[3,1846] + vP[4,1846] + vNSE[1,1846,1] - vCHARGE[4,1846] = 14.663\n cPowerBalance[1847,1] : vP[2,1847] + vP[3,1847] + vP[4,1847] + vNSE[1,1847,1] - vCHARGE[4,1847] = 13.62\n cPowerBalance[1848,1] : vP[2,1848] + vP[3,1848] + vP[4,1848] + vNSE[1,1848,1] - vCHARGE[4,1848] = 12.388","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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.","category":"page"},{"location":"Model_Reference/Resources/storage_symmetric/#Storage-Symmetric","page":"Storage Symmetric","title":"Storage Symmetric","text":"","category":"section"},{"location":"Model_Reference/Resources/storage_symmetric/","page":"Storage Symmetric","title":"Storage Symmetric","text":"Modules = [GenX]\nPages = [\"storage_symmetric.jl\"]","category":"page"},{"location":"Model_Reference/Resources/storage_symmetric/#GenX.storage_symmetric!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Symmetric","title":"GenX.storage_symmetric!","text":"storage_symmetric!(EP::Model, inputs::Dict, setup::Dict)\n\nSets up variables and constraints specific to storage resources with symmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/storage_symmetric/#GenX.storage_symmetric_operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Symmetric","title":"GenX.storage_symmetric_operational_reserves!","text":"storage_symmetric_operational_reserves!(EP::Model, inputs::Dict)\n\nSets up variables and constraints specific to storage resources with symmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/maintenance_overview/#Optimized-Scheduled-Maintenance","page":"Maintenance","title":"Optimized Scheduled Maintenance","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Added in v0.4","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"In the real world, some types of resources (notably, fission) require regular scheduled maintenance, which often takes several weeks. During this time, the plant produces no power. This module allows GenX to find the best time of year for plants to undergo maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Scheduled maintenance is implemented only for thermal plants with unit commitment (THERM=1).","category":"page"},{"location":"Model_Reference/maintenance_overview/#Description-of-the-maintenance-model","page":"Maintenance","title":"Description of the maintenance model","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"A plant requires a single contiguous period of h ge 1 hours of maintenance, every y ge 1 years. For each plant, the best time to start the maintenance period is determined by the optimizer.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"During maintenance, the plant cannot be \"commited\", and therefore","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"uses no fuel,\nproduces no power,\nand does not contribute to reserves.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Additionally, ","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"the plant does not contribute to any Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Treatment-of-plants-that-require-maintenance-only-every-few-years","page":"Maintenance","title":"Treatment of plants that require maintenance only every few years","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"GenX models a long-term equilibrium, and each problem generally represents a single full year. If a plant requires maintenance every y years, we take the simplification that at least 1y of the plants must undergo maintenance in the modeled year.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"See also \"Interaction with integer unit commitment\" below.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Reduction-of-number-of-possible-start-dates","page":"Maintenance","title":"Reduction of number of possible start dates","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"This module creates constraints which work across long periods, and consequently can be very expensive to solve. In order to reduce the expense, the set of possible maintenance start dates can be limited. Rather than have maintenance potentially start every hour, one can have possible start dates which are once per day, once per week, etc. (In reality, maintenance is likely scheduled months in advance, so optimizing down to the hour may not be realistic anyway.)","category":"page"},{"location":"Model_Reference/maintenance_overview/#How-to-use","page":"Maintenance","title":"How to use","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"There are four columns which need to be added to the plant data, i.e. in Generators_data.csv:","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"MAINT should be 1 for plants that require maintenance and 0 otherwise.\nMaintenance_Duration is the number of hours the maintenance period lasts.\nMaintenance_Cycle_Length_Years. If 1, maintenance every year, if 3 maintenance every 3 years, etc.\nMaintenance_Begin_Cadence. Spacing between hours in which maintenance can start.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The last three fields must be integers which are greater than 0. They are ignored for any plants which do not require maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Maintenance_Duration must be less than the total number of hours in the year.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If Maintenance_Begin_Cadence is 1 then the maintenance can begin in any hour. If it is 168 then it can begin in hours 1, 169, 337, etc.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Restrictions-on-use","page":"Maintenance","title":"Restrictions on use","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The maintenance module has these restrictions:","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"More than a single maintenance period per year (i.e. every three months) is not possible in the current formulation.\nOnly full-year cases can be run; there must be only one \"representative period\".","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"It would not make sense to model a month-long maintenance period when the year is modeled as a series of representative weeks, for example.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Interaction-with-integer-unit-commitment","page":"Maintenance","title":"Interaction with integer unit commitment","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If integer unit commitment is on (UCommit=1) this module may not produce correct results; there may be more maintenance than the user wants. This is because the formulation specifies that the number of plants that go down for maintenance in the simulated year must be at least (the number of plants in the zone)/(the maintenance cycle length in years). As a reminder, the number of plants is eTotalCap / Cap_Size.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If there were three 500 MW plants (total 1500 MW) in a zone, and they require maintenance every three years (Maintenance_Cycle_Length_Years=3), the formulation will work properly: one of the three plants will go under maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"But if there was only one 500 MW plant, and it requires maintenance every 3 years, the constraint will still make it do maintenance every year, because ceil(1/3) is 1. The whole 500 MW plant will do maintenance. This is the unexpected behavior.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"However, if integer unit commitment was relaxed to \"linearized\" unit commitment (UCommit=2), the model will have only 500 MW / 3 = 166.6 MW worth of this plant do maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Hint:-pre-scheduling-maintenance","page":"Maintenance","title":"Hint: pre-scheduling maintenance","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If you want to pre-schedule when maintenance occurs, you might not need this module. Instead, you could set the maximum power output of the plant to zero for a certain period, or make its fuel extremely expensive during that time. However, the plant would still be able to contribute to the Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Outputs-produced","page":"Maintenance","title":"Outputs produced","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If at least one plant has MAINT=1, a file maint_down.csv will be written listing how many plants are down for maintenance in each timestep.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Notes-on-mathematical-formulation","page":"Maintenance","title":"Notes on mathematical formulation","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The formulation of the maintenance state is very similar to the formulation of unit commitment.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"There is a variable called something like vMSHUT which is analogous to vSTART and controls the start of the maintenance period. There is another variable called something like vMDOWN analogous to vCOMMIT which controls the maintenance status in any hour.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"A constraint ensures that the value of vMDOWN in any hour is always more than the number of vMSHUTs in the previous Maintenance_Duration hours.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Another constraint ensures that the number of plants committed (vCOMMIT) at any one time plus the number of plants under maintenance (vMDOWN) is less than the total number of plants.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Developer-note:-adding-maintenance-to-a-resource","page":"Maintenance","title":"Developer note: adding maintenance to a resource","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The maintenance formulation is applied on a per-resource basis, by calling the function GenX.maintenance_formulation!. ","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"See GenX.maintenance_formulation_thermal_commit! for an example of how to apply it to a new resource.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The resource must have a vCOMMIT-like variable which is proportional to maximum the power output, etc at any given timestep.\nThe resource must have a eTotalCap-like quantity and a Cap_Size-like parameter; only the ratio of the two is used.","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/#Tutorial-2:-Network-Visualization","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"","category":"section"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"To run GenX, there are five mandatory input files: Fuels_data.csv, Network.csv, Load_data.csv, Generators_variability.csv, and Generators_data.csv. Detailed descriptions of these files can be found in the GenX Inputs page of the documentation. This tutorial helps visualize the file Network.csv using the example system example_systems/1_three_zones.","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"using CSV\nusing DataFrames","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"The input file Network.csv contains the nodes of your network, how they connect to each other, and some important features about them. Below is the network file for example_systems/1_three_zones:","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"network = CSV.read(\"example_systems/1_three_zones/system/Network.csv\",DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"
3×14 DataFrame
RowColumn1Network_zonesNetwork_LinesStart_ZoneEnd_ZoneLine_Max_Flow_MWtransmission_path_namedistance_mileLine_Loss_PercentageLine_Max_Reinforcement_MWLine_Reinforcement_Cost_per_MWyrDerateCapRes_1CapRes_1CapRes_Excl_1
String3String3String3String3String3String7String15String15String15String7String7String7String3Int64?
1MAz11122950MA_to_CT123.05840.0123058372950120600.9500
2CTz22132000MA_to_ME196.53850.0196538472000192610.9500
3MEz3missing
","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"MA, CT, and ME are the abbreviations for states Massachusetts, Connecticut, and Maine. However, since the US region of New England contains other states as well, MA in this case is also used to refer to those states.","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"Columns Start_Zone and End_Zone specify the network of the three regions. In this case, there are only two network lines, specified in the Network_Lines columns. The Start_Zone column indicates that the first node, MA, is the source of both lines as both rows have value 1. Rows z1 and z2 have values of 2 and 3 in End_Zone, which means both nodes CT and ME recieve energy from node MA. This is also indicated in the column `transmissionpathname'. ","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"Below is a visualization of the network:","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"","category":"page"},{"location":"Model_Reference/Resources/thermal_commit/#Thermal-Commit","page":"Thermal Commit","title":"Thermal Commit","text":"","category":"section"},{"location":"Model_Reference/Resources/thermal_commit/","page":"Thermal Commit","title":"Thermal Commit","text":"Modules = [GenX]\nPages = [\"thermal_commit.jl\"]","category":"page"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.maintenance_formulation_thermal_commit!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal Commit","title":"GenX.maintenance_formulation_thermal_commit!","text":"maintenance_formulation_thermal_commit!(EP::Model, inputs::Dict, setup::Dict)\n\nCreates maintenance variables and constraints for thermal-commit plants.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.thermal_commit!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal Commit","title":"GenX.thermal_commit!","text":"thermal_commit!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the operating constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decision (y in UC).\n\nWe model capacity investment decisions and commitment and cycling (start-up, shut-down) of thermal generators using the integer clustering technique developed in Palmintier, 2011, Palmintier, 2013, and Palmintier, 2014. In a typical binary unit commitment formulation, each unit is either on or off. With the clustered unit commitment formulation, one or more cluster(s) of similar generators are clustered by type and zone (typically using heat rate and fixed O\\&M cost to create clusters), and the integer commitment state variable for each cluster varies from zero to the number of units in the cluster, fracDelta^total_yzOmega^size_yz. As discussed in \\cite{Palmintier2014}, this approach replaces the large set of binary commitment decisions and associated constraints, which scale directly with the number of individual units, with a smaller set of integer commitment states and constraints, one for each cluster y. The dimensionality of the problem thus scales with the number of units of a given type in each zone, rather than by the number of discrete units, significantly improving computational efficiency. However, this method entails the simplifying assumption that all clustered units have identical parameters (e.g., capacity size, ramp rates, heat rate) and that all committed units in a given time step t are operating at the same power output per unit.\n\nPower balance expression\n\nThis function adds the sum of power generation from thermal units subject to unit commitment (Theta_y in UCt in Tz in Z) to the power balance expression.\n\nStartup and shutdown events (thermal plant cycling)\n\nCapacitated limits on unit commitment decision variables\n\nThermal resources subject to unit commitment (y in mathcalUC) adhere to the following constraints on commitment states, startup events, and shutdown events, which limit each decision to be no greater than the maximum number of discrete units installed (as per the following three constraints):\n\nbeginaligned\nnu_yzt leq fracDelta^texttotal_yzOmega^size_yz\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\nchi_yzt leq fracDelta^texttotal_yzOmega^size_yz\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\nzeta_yzt leq fracDelta^texttotal_yzOmega^size_yz\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 1-3 in the code)\n\nwhere decision nu_yzt designates the commitment state of generator cluster y in zone z at time t, decision chi_yzt represents number of startup decisions, decision zeta_yzt represents number of shutdown decisions, Delta^texttotal_yz is the total installed capacity, and parameter Omega^size_yz is the unit size.\n\nCommitment state constraint linking start-up and shut-down decisions\n\nAdditionally, the following constarint maintains the commitment state variable across time, nu_yzt, as the sum of the commitment state in the prior, nu_yzt-1, period plus the number of units started in the current period, chi_yzt, less the number of units shut down in the current period, zeta_yzt:\n\nbeginaligned\nnu_yzt =nu_yzt-1 + chi_yzt - zeta_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT^interior \nnu_yzt =nu_yzt +tau^period-1 + chi_yzt - zeta_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT^start\nendaligned\n\n(See Constraint 4 in the code)\n\nLike other time-coupling constraints, this constraint wraps around to link the commitment state in the first time step of the year (or each representative period), t in mathcalT^start, to the last time step of the year (or each representative period), t+tau^period-1.\n\nRamping constraints\n\nThermal resources subject to unit commitment (y in UC) adhere to the following ramping constraints on hourly changes in power output:\n\nbeginaligned\n\tTheta_yzt-1 + f_y z t-1+r_y z t-1 - Theta_yzt-f_y z tleq kappa^down_yz cdot Omega^size_yz cdot (nu_yzt - chi_yzt) 6pt\n\tqquad - rho^min_yz cdot Omega^size_yz cdot chi_yzt hspace05cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT 6pt\n\tqquad + textmin( rho^max_yzt textmax( rho^min_yz kappa^down_yz ) ) cdot Omega^size_yz cdot zeta_yzt \nendaligned\n\nbeginaligned\n\tTheta_yzt+f_y z t+r_y z t - Theta_yzt-1- f_y z t-1 leq kappa^up_yz cdot Omega^size_yz cdot (nu_yzt - chi_yzt) 6pt\n\tqquad + textmin( rho^max_yzt textmax( rho^min_yz kappa^up_yz ) ) cdot Omega^size_yz cdot chi_yzt hspace05cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT 6pt\n\tqquad - rho^min_yz cdot Omega^size_yz cdot zeta_yzt \nendaligned\n\n(See Constraints 5-6 in the code)\n\nwhere decision Theta_yzt, f_y z t, and r_y z t are respectively, the energy injected into the grid, regulation, and reserve by technology y in zone z at time t, parameter kappa_yzt^updown is the maximum ramp-up or ramp-down rate as a percentage of installed capacity, parameter rho_yz^min is the minimum stable power output per unit of installed capacity, and parameter rho_yzt^max is the maximum available generation per unit of installed capacity. These constraints account for the ramping limits for committed (online) units as well as faster changes in power enabled by units starting or shutting down in the current time step.\n\nMinimum and maximum power output\n\nIf not modeling regulation and spinning reserves, thermal resources subject to unit commitment adhere to the following constraints that ensure power output does not exceed minimum and maximum feasible levels:\n\nbeginaligned\n\tTheta_yzt geq rho^min_yz times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt leq rho^max_yz times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 7-8 the code)\n\nIf modeling reserves and regulation, these constraints are replaced by those established in this thermal_commit_operational_reserves().\n\nMinimum and maximum up and down time\n\nThermal resources subject to unit commitment adhere to the following constraints on the minimum time steps after start-up before a unit can shutdown again (minimum up time) and the minimum time steps after shut-down before a unit can start-up again (minimum down time):\n\nbeginaligned\n\tnu_yzt geq displaystyle sum_hatt = t-(tau^up_yz-1)^t chi_yzhatt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tfracoverlineDelta_yz + Omega_yz - Delta_yzOmega^size_yz - nu_yzt geq displaystyle sum_hatt = t-(tau^down_yz-1)^t zeta_yzhatt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 9-10 in the code)\n\nwhere tau_yz^updown is the minimum up or down time for units in generating cluster y in zone z.\n\nLike with the ramping constraints, the minimum up and down constraint time also wrap around from the start of each time period to the end of each period. It is recommended that users of GenX must use longer subperiods than the longest min up/down time if modeling UC. Otherwise, the model will report error.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.thermal_commit_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Thermal Commit","title":"GenX.thermal_commit_operational_reserves!","text":"thermal_commit_operational_reserves!(EP::Model, inputs::Dict)\n\nThis function is called by the thermal_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decisions.\n\nMaximum contributions to frequency regulation and reserves\n\nWhen modeling frequency regulation and reserves contributions, thermal units subject to unit commitment adhere to the following constraints which limit the maximum contribution to regulation and reserves in each time step to a specified maximum fraction (upsilon^rsv_yz) of the commitment capacity in that time step ((Omega^size_yz cdot nu_yzt)):\n\nbeginaligned\n\tf_yzt leq upsilon^reg_yz times rho^max_yzt (Omega^size_yz times nu_yzt) hspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tr_yzt leq upsilon^rsv_yz times rho^max_yzt (Omega^size_yz times nu_yzt) hspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nwhere f_yzt is the frequency regulation contribution limited by the maximum regulation contribution upsilon^reg_yz, and r_yzt is the reserves contribution limited by the maximum reserves contribution upsilon^rsv_yz. Limits on reserve contributions reflect the maximum ramp rate for the thermal resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nMinimum and maximum power output\n\nWhen modeling frequency regulation and spinning reserves contributions, thermal resources subject to unit commitment adhere to the following constraints that ensure the sum of power output and reserve and/or regulation contributions do not exceed minimum and maximum feasible power output:\n\nbeginaligned\n\tTheta_yzt - f_yzt geq rho^min_yz times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt + f_yzt + r_yzt leq rho^max_yzt times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.thermal_maintenance_capacity_reserve_margin_adjustment!-Tuple{JuMP.Model, Dict}","page":"Thermal Commit","title":"GenX.thermal_maintenance_capacity_reserve_margin_adjustment!","text":"thermal_maintenance_capacity_reserve_margin_adjustment!(EP::Model, inputs::Dict)\n\nEliminates the contribution of a plant to the capacity reserve margin while it is down for maintenance.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solve_model/#Solving-the-Model","page":"Solving the Model","title":"Solving the Model","text":"","category":"section"},{"location":"Model_Reference/solve_model/","page":"Solving the Model","title":"Solving the Model","text":"Modules = [GenX]\nPages = [\"solve_model.jl\"]","category":"page"},{"location":"Model_Reference/solve_model/#GenX.fix_integers-Tuple{JuMP.Model}","page":"Solving the Model","title":"GenX.fix_integers","text":"fix_integers(jump_model::Model)\n\nThis function fixes the iteger variables ones the model has been solved in order to calculate approximations of dual variables.\n\nArguments\n\njump_model::Model: a model object containing that has been previously solved.\n\nReturns\n\nnothing (modifies an existing-solved model in the memory). solve() must be run again to solve and getdual veriables\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solve_model/#GenX.solve_model-Tuple{JuMP.Model, Dict}","page":"Solving the Model","title":"GenX.solve_model","text":"solve_model(EP::Model, setup::Dict)\n\nDescription: Solves and extracts solution variables for later processing\n\nArguments\n\nEP::Model: a JuMP model representing the energy optimization problem\nsetup::Dict: a Dict containing GenX setup flags\n\nReturns\n\nEP::Model: the solved JuMP model\nsolver_time::Float64: time taken to solve the model\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/investment_charge/#Investment-Charge","page":"Investment Charge","title":"Investment Charge","text":"","category":"section"},{"location":"Model_Reference/Resources/investment_charge/","page":"Investment Charge","title":"Investment Charge","text":"Modules = [GenX]\nPages = [\"investment_charge.jl\"]","category":"page"},{"location":"Model_Reference/Resources/investment_charge/#GenX.investment_charge!-Tuple{JuMP.Model, Dict, Dict}","page":"Investment Charge","title":"GenX.investment_charge!","text":"investment_charge!(EP::Model, inputs::Dict)\n\nThis function defines the expressions and constraints keeping track of total available storage charge capacity across all resources as well as constraints on capacity retirements. The function also adds investment and fixed O\\&M related costs related to charge capacity to the objective function.\n\nThe total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity.\n\nbeginaligned\n Delta^totalcharge_yz =(overlineDelta^charge_yz+Omega^charge_yz-Delta^charge_yz) forall y in mathcalO^asym z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity.\n\nbeginaligned\nDelta^charge_yz leq overlineDelta^charge_yz\n\thspace4 cm forall y in mathcalO^asym z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^charge and underlineOmega_yz^charge is defined, then we impose constraints on minimum and maximum power capacity.\n\nbeginaligned\n Delta^totalcharge_yz leq overlineOmega^charge_yz\n\thspace4 cm forall y in mathcalO^asym z in mathcalZ \n Delta^totalcharge_yz geq underlineOmega^charge_yz\n\thspace4 cm forall y in mathcalO^asym z in mathcalZ\nendaligned\n\nIn addition, this function adds investment and fixed O&M related costs related to charge capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalO^asym sum_z in mathcalZ\n\tleft( (pi^INVESTcharge_yz times Omega^charge_yz)\n\t+ (pi^FOMcharge_yz times Delta^totalcharge_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#Co-located-VRE-Storage-Module","page":"Co-located VRE and Storage","title":"Co-located VRE-Storage Module","text":"","category":"section"},{"location":"Model_Reference/Resources/vre_stor/","page":"Co-located VRE and Storage","title":"Co-located VRE and Storage","text":"Modules = [GenX]\nPages = [\"vre_stor.jl\"]","category":"page"},{"location":"Model_Reference/Resources/vre_stor/#GenX.inverter_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.inverter_vre_stor!","text":"inverter_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the inverter component of each co-located VRE and storage generator.\n\nThe total inverter capacity of each resource is defined as the sum of the existing inverter capacity plus the newly invested inverter capacity minus any retired inverter capacity:\n\nbeginaligned\n Delta^total inv_yz = (overlineDelta^inv_yz + Omega^inv_yz - Delta^inv_yz) quad forall y in mathcalVS^inv z in mathcalZ\nendaligned\n\nOne cannot retire more inverter capacity than existing inverter capacity:\n\nbeginaligned\n Delta^inv_yz leq overlineDelta^inv_yz\n hspace4 cm forall y in mathcalVS^inv z in mathcalZ\n endaligned\n\nFor resources where overlineOmega^inv_yz and underlineOmega^inv_yz are defined, then we impose constraints on minimum and maximum capacity:\n\nbeginaligned\n Delta^total inv_yz leq overlineOmega^inv_yz\n hspace4 cm forall y in mathcalVS^inv z in mathcalZ \n Delta^total inv_yz geq underlineOmega^inv_yz\n hspace4 cm forall y in mathcalVS^inv z in mathcalZ\nendaligned\n\nThe last constraint ensures that the maximum DC grid exports and imports must be less than the inverter capacity. Without any capacity reserve margin or operating reserves, the constraint is:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt) + fracPi_yzt^dceta^inverter_yz leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nWith only capacity reserve margins, the maximum DC grid exports and imports constraint becomes:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt + Theta^CRMdc_yzt) + fracPi_yzt^dc + Pi_yzt^CRMdceta^inverter_yz \n leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nWith only operating reserves, the maximum DC grid exports and imports constraint becomes:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt + f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) + fracPi_yzt^dc + f^dccha_yzteta^inverter_yz \n leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nWith both capacity reserve margins and operating reserves, the maximum DC grid exports and imports constraint becomes:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt + Theta^CRMdc_yzt + f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) \n + fracPi_yzt^dc + Pi_yzt^CRMdc + f^dccha_yzteta^inverter_yz leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nIn addition, this function adds investment and fixed O&M related costs related to the inverter capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^inv sum_z in mathcalZ\n left( (pi^INVEST inv_yz times Omega^inv_yz)\n + (pi^FOM inv_yz times Delta^totalinv_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.investment_charge_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.investment_charge_vre_stor!","text":"investment_charge_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function activates the decision variables and constraints for asymmetric storage resources (independent charge and discharge power capacities (any STOR flag = 2)). For asymmetric storage resources, the function is enabled so charging and discharging can occur either through DC or AC capabilities. For example, a storage resource can be asymmetrically charged and discharged via DC capabilities or a storage resource could be charged via AC capabilities and discharged through DC capabilities. This module is configured such that both AC and DC charging (or discharging) cannot simultaneously occur.\n\nThe total charge/discharge DC and AC capacities of each resource are defined as the sum of the existing charge/discharge DC and AC capacities plus the newly invested charge/discharge DC and AC capacities minus any retired charge/discharge DC and AC capacities:\n\nbeginaligned\n Delta^totaldcdis_yz =(overlineDelta^dcdis_yz+Omega^dcdis_yz-Delta^dcdis_yz) quad forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^totaldccha_yz =(overlineDelta^dccha_yz+Omega^dccha_yz-Delta^dccha_yz) quad forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^totalacdis_yz =(overlineDelta^acdis_yz+Omega^acdis_yz-Delta^acdis_yz) quad forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^totalaccha_yz =(overlineDelta^accha_yz+Omega^accha_yz-Delta^accha_yz) quad forall y in mathcalVS^asymaccha z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity:\n\nbeginaligned\n Delta^dcdis_yz leq overlineDelta^dcdis_yz\n hspace4 cm forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^dccha_yz leq overlineDelta^dccha_yz\n hspace4 cm forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^acdis_yz leq overlineDelta^acdis_yz\n hspace4 cm forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^accha_yz leq overlineDelta^accha_yz\n hspace4 cm forall y in mathcalVS^asymaccha z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^dcdis overlineOmega_yz^dccha overlineOmega_yz^acdis overlineOmega_yz^accha and underlineOmega_yz^dcdis underlineOmega_yz^dccha underlineOmega_yz^acdis underlineOmega_yz^ac cha are defined, then we impose constraints on minimum and maximum charge/discharge DC and AC power capacity:\n\nbeginaligned\n Delta^totaldcdis_yz leq overlineOmega^dcdis_yz\n hspace4 cm forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^totaldcdis_yz geq underlineOmega^dcdis_yz\n hspace4 cm forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^totaldccha_yz leq overlineOmega^dccha_yz\n hspace4 cm forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^totaldccha_yz geq underlineOmega^dccha_yz\n hspace4 cm forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^totalacdis_yz leq overlineOmega^acdis_yz\n hspace4 cm forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^totalacdis_yz geq underlineOmega^acdis_yz\n hspace4 cm forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^totalaccha_yz leq overlineOmega^accha_yz\n hspace4 cm forall y in mathcalVS^asymaccha z in mathcalZ \n Delta^totalaccha_yz geq underlineOmega^accha_yz\n hspace4 cm forall y in mathcalVS^asymaccha z in mathcalZ \nendaligned\n\nFurthermore, for storage technologies with asymmetric charge and discharge capacities (all y in mathcalVS^asymdcdis y in mathcalVS^asymdccha y in mathcalVS^asymacdis y in mathcalVS^asymaccha), the charge rate, Pi^dc_yzt Pi^ac_yzt, is constrained by the total installed charge capacity, Delta^totaldccha_yz Delta^totalaccha_yz. Similarly the discharge rate, Theta^dc_yzt Theta^ac_yzt, is constrained by the total installed discharge capacity, Delta^totaldcdis_yz Delta^totalacdis_yz. Without any activated capacity reserve margin policies or operating reserves, the constraints are as follows:\n\nbeginaligned\n Theta^dc_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nAdding only the capacity reserve margin constraints, the asymmetric charge and discharge DC and AC rates plus the 'virtual' charge and discharge DC and AC rates are constrained by the total installed charge and discharge DC and AC capacities:\n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt + Pi^CRMdc_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt + Pi^CRMac_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nAdding only the operating reserve constraints, the asymmetric charge and discharge DC and AC rates plus the contributions to frequency regulation and operating reserves (both DC and AC) are constrained by the total installed charge and discharge DC and AC capacities:\n\nbeginaligned\n Theta^dc_yzt + f^dcdis_yzt + r^dcdis_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt + f^dccha_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt + f^acdis_yzt + r^acdis_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt + f^accha_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nWith both capacity reserve margin and operating reserve constraints, the asymmetric charge and discharge DC and AC rate constraints follow: \n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt + f^dcdis_yzt + r^dcdis_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt + Pi^CRMdc_yzt + f^dccha_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt + f^acdis_yzt + r^acdis_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt + Pi^CRMac_yzt + f^accha_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nIn addition, this function adds investment and fixed O&M costs related to charge/discharge AC and DC capacities to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^asymdcdis sum_z in mathcalZ\n left( (pi^INVESTdcdis_yz times Omega^dcdis_yz)\n + (pi^FOMdcdis_yz times Delta^totaldcdis_yz)right) \n \t+ sum_y in mathcalVS^asymdccha sum_z in mathcalZ\n left( (pi^INVESTdccha_yz times Omega^dccha_yz)\n + (pi^FOMdccha_yz times Delta^totaldccha_yz)right) \n \t+ sum_y in mathcalVS^asymacdis sum_z in mathcalZ\n left( (pi^INVESTacdis_yz times Omega^acdis_yz)\n + (pi^FOMacdis_yz times Delta^totalacdis_yz)right) \n \t+ sum_y in mathcalVS^asymaccha sum_z in mathcalZ\n left( (pi^INVESTaccha_yz times Omega^accha_yz)\n + (pi^FOMaccha_yz times Delta^totalaccha_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.lds_vre_stor!-Tuple{JuMP.Model, Dict}","page":"Co-located VRE and Storage","title":"GenX.lds_vre_stor!","text":"lds_vre_stor!(EP::Model, inputs::Dict)\n\nThis function defines the decision variables, expressions, and constraints for any long duration energy storage component of each co-located VRE and storage generator ( there is more than one representative period and LDS_VRE_STOR=1 in the Vre_and_stor_data.csv). \n\nThese constraints follow the same formulation that is outlined by the function long_duration_storage!() in the storage module. One constraint changes, which links the state of charge between the start of periods for long duration energy storage resources because there are options to charge and discharge these resources through AC and DC capabilities. The main linking constraint changes to:\n\nbeginaligned\n Gamma_yz(m-1)times tau^period+1 =left(1-eta_yz^lossright) times left(Gamma_yzmtimes tau^period -Delta Q_yzmright) \n - fracTheta^dc_yz(m-1) times tau^period+1eta_yz^dischargedc - fracTheta^ac_yz(m-1)times tau^period+1eta_yz^dischargeac \n + eta_yz^chargedc times Pi^dc_yz(m-1)times tau^period+1 + eta_yz^chargeac times Pi^ac_yz(m-1)times tau^period+1 quad forall y in mathcalVS^LDES z in mathcalZ m in mathcalM\nendaligned\n\nThe rest of the long duration energy storage constraints are copied and applied to the co-located VRE and storage module for any long duration energy storage resources y in mathcalVS^LDES from the long-duration storage module. Capacity reserve margin constraints for long duration energy storage resources are further elaborated upon in vre_stor_capres!().\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.solar_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.solar_vre_stor!","text":"solar_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the solar PV component of each co-located VRE and storage generator.\n\nThe total solar PV capacity of each resource is defined as the sum of the existing solar PV capacity plus the newly invested solar PV capacity minus any retired solar PV capacity:\n\nbeginaligned\n Delta^total pv_yz = (overlineDelta^pv_yz + Omega^pv_yz - Delta^pv_yz) quad forall y in mathcalVS^pv z in mathcalZ\nendaligned\n\nOne cannot retire more solar PV capacity than existing solar PV capacity:\n\nbeginaligned\n Delta^pv_yz leq overlineDelta^pv_yz\n hspace4 cm forall y in mathcalVS^pv z in mathcalZ\nendaligned\n\nFor resources where overlineOmega^pv_yz and underlineOmega^pv_yz are defined, then we impose constraints on minimum and maximum capacity:\n\nbeginaligned\n Delta^total pv_yz leq overlineOmega^pv_yz\n hspace4 cm forall y in mathcalVS^pv z in mathcalZ \n Delta^total pv_yz geq underlineOmega^pv_yz\n hspace4 cm forall y in mathcalVS^pv z in mathcalZ\nendaligned\n\nIf there is a fixed ratio for capacity (rather than co-optimizing interconnection sizing) of solar PV built to capacity of inverter built (eta_yz^ILRpv), also known as the inverter loading ratio, then we impose the following constraint:\n\nbeginaligned\n Delta^total pv_y z = eta^ILRpv_y z times Delta^total inv_y z quad forall y in mathcalVS^pv forall z in Z\nendaligned\n\nThe last constraint defines the maximum power output in each time step from the solar PV component. Without any operating reserves, the constraint is:\n\nbeginaligned\n Theta^pv_y z t leq rho^max pv_y z t times Delta^totalpv_y z quad forall y in mathcalVS^pv forall z in Z forall t in T\nendaligned\n\nWith operating reserves, the maximum power output in each time step from the solar PV component must account for procuring some of the available capacity for frequency regulation (f^pv_yzt) and upward operating (spinning) reserves (r^pv_yzt):\n\nbeginaligned\n Theta^pv_y z t + f^pv_yzt + r^pv_yzt leq rho^max pv_y z t times Delta^totalpv_y z quad forall y in mathcalVS^pv forall z in Z forall t in T\nendaligned\n\nIn addition, this function adds investment, fixed O&M, and variable O&M costs related to the solar PV capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^pv sum_z in mathcalZ\n left( (pi^INVEST pv_yz times Omega^pv_yz) + (pi^FOM pv_yz times Delta^totalpv_yz) right) \n + sum_y in mathcalVS^pv sum_z in mathcalZ sum_t in mathcalT (pi^VOM pv_yz times eta^inverter_yz times Theta^pv_yzt)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.stor_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.stor_vre_stor!","text":"stor_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the storage component of each co-located VRE and storage generator. A wide range of energy storage devices (all y in mathcalVS^stor) can be modeled in GenX, using one of two generic storage formulations: (1) storage technologies with symmetric charge and discharge capacity (all y in mathcalVS^symdc cup y in mathcalVS^symac), such as lithium-ion batteries and most other electrochemical storage devices that use the same components for both charge and discharge; and (2) storage technologies that employ distinct and potentially asymmetric charge and discharge capacities (all y in mathcalVS^asymdcdis cup y in mathcalVS^asymdccha cup y in mathcalVS^asymacdis cup y in mathcalVS^asymaccha), such as most thermal storage technologies or hydrogen electrolysis/storage/fuel cell or combustion turbine systems. The following constraints apply to all storage resources, y in mathcalVS^stor, regardless of whether or not the storage has symmetric or asymmetric charging/discharging capabilities or varying durations of discharge. \n\nThe total storage energy capacity of each resource is defined as the sum of the existing storage energy capacity plus the newly invested storage energy capacity minus any retired storage energy capacity:\n\nbeginaligned\n Delta^totalenergy_yz = (overlineDelta^energy_yz+Omega^energy_yz-Delta^energy_yz) quad forall y in mathcalVS^stor z in mathcalZ\nendaligned\n\nOne cannot retire more energy capacity than existing energy capacity:\n\nbeginaligned\n Delta^energy_yz leq overlineDelta^energy_yz\n hspace4 cm forall y in mathcalVS^stor z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^energy and underlineOmega_yz^energy are defined, then we impose constraints on minimum and maximum energy capacity:\n\nbeginaligned\n Delta^totalenergy_yz leq overlineOmega^energy_yz\n hspace4 cm forall y in mathcalVS^stor z in mathcalZ \n Delta^totalenergy_yz geq underlineOmega^energy_yz\n hspace4 cm forall y in mathcalVS^stor z in mathcalZ\nendaligned\n\nThe following two constraints track the state of charge of the storage resources at the end of each time period, relating the volume of energy stored at the end of the time period, Gamma_yzt, to the state of charge at the end of the prior time period, Gamma_yzt-1, the DC and AC charge and discharge decisions in the current time period, Pi^dc_yzt Pi^ac_yzt Theta^dc_yzt Theta^ac_yzt, and the self discharge rate for the storage resource (if any), eta_yz^loss. When modeling the entire year as a single chronological period with total number of time steps of tau^period, storage inventory in the first time step is linked to storage inventory at the last time step of the period representing the year. Alternatively, when modeling the entire year with multiple representative periods, this constraint relates storage inventory in the first timestep of the representative period with the inventory at the last time step of the representative period, where each representative period is made of tau^period time steps. In this implementation, energy exchange between representative periods is not permitted. When modeling representative time periods, GenX enables modeling of long duration energy storage which tracks state of charge between representative periods enable energy to be moved throughout the year. If there is more than one representative period and LDS_VRE_STOR=1 has been enabled for resources in Vre_and_stor_data.csv, this function calls lds_vre_stor!() to enable this feature. The first of these two constraints enforces storage inventory balance for interior time steps (t in mathcalT^interior), while the second enforces storage balance constraint for the initial time step (t in mathcalT^start):\n\nbeginaligned\n\t Gamma_yzt = Gamma_yzt-1 - fracTheta^dc_yzteta_yz^dischargedc - fracTheta^ac_yzteta_yz^dischargeac + eta_yz^chargedc times Pi^dc_yzt + eta_yz^chargeac times Pi^ac_yzt \n - eta_yz^loss times Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^interior\n\t Gamma_yzt = Gamma_yzt+tau^period-1 - fracTheta^dc_yzteta_yz^dischargedc - fracTheta^ac_yzteta_yz^dischargeac + eta_yz^chargedc times Pi^dc_yzt + eta_yz^chargeac times Pi^ac_yzt \n - eta_yz^loss times Gamma_yzt+tau^period-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^start\nendaligned\n\nThe last constraint limits the volume of energy stored at any time, Gamma_yzt, to be less than the installed energy storage capacity, Delta^total energy_yz. \n\nbeginaligned\n\t Gamma_yzt leq Delta^total energy_yz quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nThe next set of constraints only apply to symmetric storage resources (all y in mathcalVS^symdc cup y in mathcalVS^symac). For storage technologies with symmetric charge and discharge capacity (all y in mathcalVS^symdc cup y in mathcalVS^symac), since storage resources generally represent a 'cluster' of multiple similar storage devices of the same type/cost in the same zone, GenX permits storage resources to simultaneously charge and discharge (as some units could be charging while others discharge). The simultaneous sum of DC and AC charge, Pi^dc_yzt Pi^ac_yzt, and discharge, Theta^dc_yzt Theta^ac_yzt, is limited by the total installed energy capacity, Delta^total energy_oz, multiplied by the power to energy ratio, mu_yz^dcstor mu_yz^acstor. Without any capacity reserve margin constraints or operating reserves, the symmetric AC and DC storage resources are constrained as:\n\nbeginaligned\n\t Theta^dc_yzt + Pi^dc_yzt leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + Pi^ac_yzt leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nSymmetric storage resources with only capacity reserve margin constraints follow a similar constraint that incorporates the 'virtual' discharging and charging that occurs and limits the simultaneously charging, discharging, virtual charging, and virtual discharging of the battery resource: \n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt + Pi^dc_yzt + Pi^CRMdc_yzt \n leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt + Pi^ac_yzt + Pi^CRMac_yzt \n leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nSymmetric storage resources only subject to operating reserves have additional variables to represent contributions of frequency regulation and upwards operating reserves while the storage is charging DC or AC (f^dccha_yzt f^accha_yzt) and discharging DC or AC (f^dcdis_yzt f^acdis_yzt r^dcdis_yzt r^acdis_yzt). Note that as storage resources can contribute to regulation and reserves while either charging or discharging, the proxy variables f^dccha_yzt f^accha_yzt f^dcdis_yzt f^acdis_yzt r^dcdis_yzt r^acdis_yzt are created for storage components.\n\nbeginaligned\n Theta^dc_yzt + f^dcdis_yzt + r^dcdis_yzt + Pi^dc_yzt + f^dccha_yzt \n leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + f^acdis_yzt + r^acdis_yzt + Pi^ac_yzt + f^accha_yzt \n leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nFor symmetric storage resources with both capacity reserve margin and operating reserves, DC and AC resources are subject to the following constraints:\n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt + f^dcdis_yzt + r^dcdis_yzt + Pi^dc_yzt + Pi^CRMdc_yzt + f^dccha_yzt \n leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt + f^acdis_yzt + r^acdis_yzt + Pi^ac_yzt + Pi^CRMac_yzt + f^accha_yzt \n leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nLong duration energy storage constraints are activated by the function lds_vre_stor!(). Asymmetric storage resource constraints are activated by the function investment_charge_vre_stor!().\n\nIn addition, this function adds investment, fixed O&M, and variable O&M costs related to the storage capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^stor sum_z in mathcalZ\n left( (pi^INVEST energy_yz times Omega^energy_yz) + (pi^FOM energy_yz times Delta^totalenergy_yz) right) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis sum_z in mathcalZ sum_t in mathcalT (pi^VOMdcdis_yz times eta^inverter_yz times Theta^dc_yzt) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdccha sum_z in mathcalZ sum_t in mathcalT (pi^VOMdccha_yz times fracPi^dc_yzteta^inverter_yz) \n + sum_y in mathcalVS^symac cup mathcalVS^asymacdis sum_z in mathcalZ sum_t in mathcalT (pi^VOMacdis_yz times Theta^ac_yzt) \n + sum_y in mathcalVS^symac cup mathcalVS^asymaccha sum_z in mathcalZ sum_t in mathcalT (pi^VOMaccha_yz times Pi^ac_yzt)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.vre_stor!","text":"vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis module enables the modeling of 1) co-located VRE and energy storage technologies, and 2) optimized interconnection sizing for VREs. Utility-scale solar PV and/or wind VRE technologies can be modeled at the same site with or without storage technologies. Storage resources can be charged/discharged behind the meter through the inverter (DC) and through AC charging/discharging capabilities. Each resource can be configured to have any combination of the following components: solar PV, wind, DC discharging/charging storage, and AC discharging/charging storage resources. For storage resources, both long duration energy storage and short-duration energy storage can be modeled, via asymmetric or symmetric charging and discharging options. Each resource connects to the grid via a grid connection component, which is the only required decision variable that each resource must have. If the configured resource has either solar PV and/or DC discharging/charging storage capabilities, an inverter decision variable is also created. The full module with the decision variables and interactions can be found below. \n\n(Image: Configurable Co-located VRE and Storage Module Interactions and Decision Variables) Figure. Configurable Co-located VRE and Storage Module Interactions and Decision Variables\n\nThis module is split such that functions are called for each configurable component of a co-located resource: inverter_vre_stor(), solar_vre_stor!(), wind_vre_stor!(), stor_vre_stor!(), lds_vre_stor!(), and investment_charge_vre_stor!(). The function vre_stor!() specifically ensures that all necessary functions are called to activate the appropriate constraints, creates constraints that apply to multiple components (i.e. inverter and grid connection balances and maximums), and activates all of the policies that have been created (minimum capacity requirements, maximum capacity requirements, capacity reserve margins, operating reserves, and energy share requirements can all be turned on for this module). Note that not all of these variables are indexed by each co-located VRE and storage resource (for example, some co-located resources may only have a solar PV component and battery technology or just a wind component). Thus, the function vre_stor!() ensures indexing issues do not arise across the various potential configurations of co-located VRE and storage module but showcases all constraints as if each decision variable (that may be only applicable to certain components) is indexed by each y in mathcalVS for readability. \n\nThe first constraint is created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains and regardless of the policies invoked for the module. This constraint represents the energy balance, ensuring net DC power (discharge of battery, PV generation, and charge of battery) and net AC power (discharge of battery, wind generation, and charge of battery) are equal to the technology's total discharging to and charging from the grid:\n\nbeginaligned\n Theta_yzt - Pi_yzt = Theta_yzt^wind + Theta_yzt^ac - Pi_yzt^ac + eta^inverter_yz times (Theta_yzt^pv + Theta_yzt^dc) - fracPi^dc_yzteta^inverter_yz \n forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint is also created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains. However, this constraint changes when either or both capacity reserve margins and operating reserves are activated. The following constraint enforces that the maximum grid exports and imports must be less than the grid connection capacity (without any policies):\n\nbeginaligned\n Theta_yzt + Pi_yzt leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint with only capacity reserve margins activated is:\n\nbeginaligned\n Theta_yzt + Pi_yzt + Theta^CRMac_yzt + Pi^CRMac_yzt + eta^inverter_yz times Theta^CRMdc_yzt + fracPi^CRMdc_yzteta^inverter_yz \n leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint with only operating reserves activated is:\n\nbeginaligned\n Theta_yzt + Pi_yzt + f^acdis_yzt + r^acdis_yzt + f^accha_yzt + f^wind_yzt + r^wind_yzt \n + eta^inverter_yz times (f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) + fracf^dccha_yzteta^inverter_yz leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint with both capacity reserve margins and operating reserves activated is:\n\nbeginaligned\n Theta_yzt + Pi_yzt + Theta^CRMac_yzt + Pi^CRMac_yzt + f^acdis_yzt + r^acdis_yzt + f^accha_yzt + f^wind_yzt + r^wind_yzt \n + eta^inverter_yz times (Theta^CRMdc_yzt + f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) + fracPi^CRMdc_yzt + f^dccha_yzteta^inverter_yz \n leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe rest of the constraints are dependent upon specific configurable components within the module and are listed below.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.vre_stor_capres!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.vre_stor_capres!","text":"vre_stor_capres!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function activates capacity reserve margin constraints for co-located VRE and storage resources. The capacity reserve margin formulation for GenX is further elaborated upon in cap_reserve_margin!(). For co-located resources (y in mathcalVS), the available capacity to contribute to the capacity reserve margin is the net injection into the transmission network (which can come from the solar PV, wind, and/or storage component) plus the net virtual injection corresponding to charge held in reserve (which can only come from the storage component), derated by the derating factor. If a capacity reserve margin is modeled, variables for virtual charge DC, Pi^CRM dc_yzt, virtual charge AC, Pi^CRM ac_yzt, virtual discharge DC, Theta^CRM dc_yzt, virtual discharge AC, Theta^CRM ac_ozt, and virtual state of charge, Gamma^CRM_yzt, are created to represent contributions that a storage device makes to the capacity reserve margin without actually generating power. These represent power that the storage device could have discharged or consumed if called upon to do so, based on its available state of charge. Importantly, a dedicated set of variables and constraints are created to ensure that any virtual contributions to the capacity reserve margin could be made as actual charge/discharge if necessary without affecting system operations in any other timesteps (similar to the standalone storage capacity reserve margin constraints). \n\nIf a capacity reserve margin is modeled, then the following constraints track the relationship between the virtual charge variables, Pi^CRMdc_yzt Pi^CRMac_yzt, virtual discharge variables, Theta^CRM dc_yzt Theta^CRM ac_yzt, and the virtual state of charge, Gamma^CRM_yzt, representing the amount of state of charge that must be held in reserve to enable these virtual capacity reserve margin contributions and ensuring that the storage device could deliver its pledged capacity if called upon to do so without affecting its operations in other timesteps. Gamma^CRM_yzt is tracked similarly to the devices' overall state of charge based on its value in the previous timestep and the virtual charge and discharge in the current timestep. Unlike the regular state of charge, virtual discharge Theta^CRMdc_yzt Theta^CRMac_yzt increases Gamma^CRM_yzt (as more charge must be held in reserve to support more virtual discharge), and the virtual charge Pi^CRMdc_yzt Pi^CRMac_yzt reduces Gamma^CRM_yzt. Similar to the state of charge constraints in the stor_vre_stor!() function, the first of these two constraints enforces storage inventory balance for interior time steps (t in mathcalT^interior), while the second enforces storage balance constraint for the initial time step (t in mathcalT^start):\n\nbeginaligned\n\t Gamma^CRM_yzt = Gamma^CRM_yzt-1 + fracTheta^CRM dc_yzteta_yz^dischargedc + fracTheta^CRMac_yzteta_yz^dischargeac - eta_yz^chargedc times Pi^CRMdc_yzt - eta_yz^chargeac times Pi^CRM ac_yzt \n - eta_yz^loss times Gamma^CRM_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^interior\n Gamma^CRM_yzt = Gamma^CRM_yzt+tau^period-1 + fracTheta^CRMdc_yzteta_yz^dischargedc + fracTheta^CRMac_yzteta_yz^dischargeac - eta_yz^chargedc times Pi^CRMdc_yzt - eta_yz^chargeac times Pi^CRMac_yzt \n - eta_yz^loss times Gamma^CRM_yzt+tau^period-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^start\nendaligned\n\nThe energy held in reserve, Gamma^CRM_yzt, also acts as a lower bound on the overall state of charge Gamma_yzt. This ensures that the storage device cannot use state of charge that would not have been available had it been called on to actually contribute its pledged virtual discharge at some earlier timestep. This relationship is described by the following constraint (as also outlined in the storage module):\n\nbeginaligned\n\t Gamma_yzt geq Gamma^CRM_yzt quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT \nendaligned\n\nThe overall contribution of the co-located VRE and storage resources to the system's capacity reserve margin in timestep t is equal to (including both actual and virtual DC and AC charge and discharge):\n\nbeginaligned\n\t sum_y in mathcalVS^pv (epsilon_yzp^CRM times eta^inverter_yz times rho^maxpv_yzt times Delta^totalpv_yz) \n + sum_y in mathcalVS^wind (epsilon_yzp^CRM times rho^maxwind_yzt times Delta^totalwind_yz) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis (epsilon_yzp^CRM times eta^inverter_yz times (Theta^dc_yzt + Theta^CRMdc_yzt)) \n + sum_y in mathcalVS^symac cup mathcalVS^asymacdis (epsilon_yzp^CRM times (Theta^ac_yzt + Theta^CRMac_yzt)) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times fracPi^dc_yzt + Pi^CRMdc_yzteta^inverter_yz) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times (Pi^ac_yzt + Pi^CRMac_yzt))\nendaligned\n\nIf long duration energy storage resources exist, a separate but similar set of variables and constraints is used to track the evolution of energy held in reserves across representative periods, which is elaborated upon in the long_duration_storage!() function. The main linking constraint follows (due to the capabilities of virtual DC and AC discharging and charging):\n\nbeginaligned\n Gamma^CRM_yz(m-1)times tau^period+1 = left(1-eta_yz^lossright)times left(Gamma^CRM_yzmtimes tau^period -Delta Q_yzmright) \n + fracTheta^CRMdc_yz(m-1)times tau^period+1eta_yz^dischargedc + fracTheta^CRMac_yz(m-1)times tau^period+1eta_yz^dischargeac \n - eta_yz^chargedc times Pi^CRMdc_yz(m-1)times tau^period+1 - eta_yz^chargeac times Pi^CRMac_yz(m-1)times tau^period+1 \n forall y in mathcalVS^LDES z in mathcalZ m in mathcalM\nendaligned\n\nAll other constraints are identical to those used to track the actual state of charge, except with the new variables for the representation of 'virtual' state of charge, build up storage inventory and state of charge at the beginning of each period. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.vre_stor_operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.vre_stor_operational_reserves!","text":"vre_stor_operational_reserves!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function activates either or both frequency regulation and operating reserve options for co-located VRE-storage resources. Co-located VRE and storage resources (y in mathcalVS) have six pairs of auxilary variables to reflect contributions to regulation and reserves when generating electricity from solar PV or wind resources, DC charging and discharging from storage resources, and AC charging and discharging from storage resources. The primary variables (f_yzt & r_yzt) becomes equal to the sum of these auxilary variables as follows:\n\nbeginaligned\n f_yzt = f^pv_yzt + f^wind_yzt + f^dcdis_yzt + f^dccha_yzt + f^acdis_yzt + f^accha_yzt quad forall y in mathcalVS z in mathcalZ t in mathcalT\n r_yzt = r^pv_yzt + r^wind_yzt + r^dcdis_yzt + r^dccha_yzt + r^acdis_yzt + r^accha_yzt quad forall y in mathcalVS z in mathcalZ t in mathcalT\nendaligned\n\nFurthermore, the frequency regulation and operating reserves require the maximum contribution from the entire resource to be a specified fraction of the installed grid connection capacity:\n\nbeginaligned\n f_yzt leq upsilon^reg_yz times Delta^total_yz\n hspace4 cm forall y in mathcalVS z in mathcalZ t in mathcalT \n r_yzt leq upsilon^rsv_yztimes Delta^total_yz\n hspace4 cm forall y in mathcalVS z in mathcalZ t in mathcalT\n endaligned\n\nThe following constraints follow if the configurable co-located resource has any type of storage component. When charging, reducing the DC and AC charge rate is contributing to upwards reserve and frequency regulation as it drops net demand. As such, the sum of the DC and AC charge rate plus contribution to regulation and reserves up must be greater than zero. Additionally, the DC and AC discharge rate plus the contribution to regulation must be greater than zero:\n\nbeginaligned\n Pi^dc_yzt - f^dccha_yzt - r^dccha_yzt geq 0 quad forall y in mathcalVS^symdc cup mathcalVS^asymdccha z in mathcalZ t in mathcalT\n Pi^ac_yzt - f^accha_yzt - r^accha_yzt geq 0 quad forall y in mathcalVS^symac cup mathcalVS^asymaccha z in mathcalZ t in mathcalT\n Theta^dc_yzt - f^dcdis_yzt geq 0 quad forall y in mathcalVS^symdc cup mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n Theta^ac_yzt - f^acdis_yzt geq 0 quad forall y in mathcalVS^symac cup mathcalVS^asymacdis z in mathcalZ t in mathcalT\nendaligned\n\nAdditionally, when reserves are modeled, the maximum DC and AC charge rate and contribution to regulation while charging can be no greater than the available energy storage capacity, or the difference between the total energy storage capacity, Delta^total energy_yz, and the state of charge at the end of the previous time period, Gamma_yzt-1, while accounting for charging losses eta_yz^chargedc eta_yz^chargeac. Note that for storage to contribute to reserves down while charging, the storage device must be capable of increasing the charge rate (which increases net load):\n\nbeginaligned\n eta_yz^chargedc times (Pi^dc_yzt + f^dccha_ozt) + eta_yz^chargeac times (Pi^ac_yzt + f^accha_ozt) \n leq Delta^energy total_yz - Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nFinally, the maximum DC and AC discharge rate and contributions to the frequency regulation and operating reserves must be less than the state of charge in the previous time period, Gamma_yzt-1. Without any capacity reserve margin policies activated, the constraint is as follows:\n\nbeginaligned\n fracTheta^dc_yzt+f^dcdis_yzt+r^dcdis_yzteta_yz^dischargedc + fracTheta^ac_yzt+f^acdis_yzt+r^acdis_yzteta_yz^dischargeac \n leq Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nWith the capacity reserve margin policies, the maximum DC and AC discharge rate accounts for both contributions to the capacity reserve margin and operating reserves as follows:\n\nbeginaligned\n fracTheta^dc_yzt+Theta^CRMdc_yzt+f^dcdis_yzt+r^dcdis_yzteta_yz^dischargedc + fracTheta^ac_yzt+Theta^CRMac_yzt+f^acdis_yzt+r^acdis_yzteta_yz^dischargeac \n leq Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nLastly, if the co-located resource has a variable renewable energy component, the solar PV and wind resource can also contribute to frequency regulation reserves and must be greater than zero:\n\nbeginaligned\n Theta^pv_yzt - f^pv_yzt geq 0 quad forall y in mathcalVS^pv z in mathcalZ t in mathcalT \n Theta^wind_yzt - f^wind_yzt geq 0 quad forall y in mathcalVS^wind z in mathcalZ t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.wind_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.wind_vre_stor!","text":"wind_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the wind component of each co-located VRE and storage generator.\n\nThe total wind capacity of each resource is defined as the sum of the existing wind capacity plus the newly invested wind capacity minus any retired wind capacity:\n\nbeginaligned\n Delta^total wind_yz = (overlineDelta^wind_yz + Omega^wind_yz - Delta^wind_yz) quad forall y in mathcalVS^wind z in mathcalZ\nendaligned\n\nOne cannot retire more wind capacity than existing wind capacity:\n\nbeginaligned\n Delta^wind_yz leq overlineDelta^wind_yz\n hspace4 cm forall y in mathcalVS^wind z in mathcalZ\nendaligned\n\nFor resources where overlineOmega^wind_yz and underlineOmega^wind_yz are defined, then we impose constraints on minimum and maximum capacity:\n\nbeginaligned\n Delta^total wind_yz leq overlineOmega^wind_yz\n hspace4 cm forall y in mathcalVS^wind z in mathcalZ \n Delta^total wind_yz geq underlineOmega^wind_yz\n hspace4 cm forall y in mathcalVS^wind z in mathcalZ\nendaligned\n\nIf there is a fixed ratio for capacity (rather than co-optimizing interconnection sizing) of wind built to capacity of grid connection built (eta_yz^ILRwind), then we impose the following constraint:\n\nbeginaligned\n Delta^total wind_y z = eta^ILRwind_y z times Delta^total_y z quad forall y in mathcalVS^wind forall z in Z\nendaligned\n\nThe last constraint defines the maximum power output in each time step from the wind component. Without any operating reserves, the constraint is:\n\nbeginaligned\n Theta^wind_y z t leq rho^max wind_y z t times Delta^totalwind_y z quad forall y in mathcalVS^wind forall z in Z forall t in T\nendaligned\n\nWith operating reserves, the maximum power output in each time step from the wind component must account for procuring some of the available capacity for frequency regulation (f^wind_yzt) and upward operating (spinning) reserves (r^wind_yzt):\n\nbeginaligned\n Theta^wind_y z t + f^wind_yzt + r^wind_yzt leq rho^max wind_y z t times Delta^totalwind_y z quad forall y in mathcalVS^wind forall z in Z forall t in T\nendaligned\n\nIn addition, this function adds investment, fixed O&M, and variable O&M costs related to the wind capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^wind sum_z in mathcalZ\n left( (pi^INVEST wind_yz times Omega^wind_yz) + (pi^FOM wind_yz times Delta^totalwind_yz) right) \n + sum_y in mathcalVS^wind sum_z in mathcalZ sum_t in mathcalT (pi^VOM wind_yz times Theta^wind_yzt)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor","text":"write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage specific files.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor_capacity-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor_capacity","text":"write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage capacities.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor_charge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor_charge","text":"write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage charging decision variables/expressions.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor_discharge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor_discharge","text":"write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage discharging decision variables/expressions.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Reading-Input-Files","page":"Inputs Functions","title":"Reading Input Files","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_inputs.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.get_systemfiles_path-Tuple{Dict, AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.get_systemfiles_path","text":"get_systemfiles_path(setup::Dict, TDR_directory::AbstractString, path::AbstractString)\n\nDetermine the directory based on the setup parameters.\n\nThis function checks if the TimeDomainReduction setup parameter is equal to 1 and if time domain reduced files exist in the data directory. If the condition is met, it returns the path to the TDR_results data directory. Otherwise, it returns the system directory specified in the setup.\n\nParameters:\n\nsetup: Dict{String, Any} - The GenX settings parameters containing TimeDomainReduction and SystemFolder information.\nTDR_directory: String - The data directory where files are located.\npath: String - Path to the case folder.\n\nReturns:\n\nString: The directory path based on the setup parameters.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_inputs-Tuple{Dict, AbstractString}","page":"Inputs Functions","title":"GenX.load_inputs","text":"load_inputs(setup::Dict,path::AbstractString)\n\nLoads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function\n\ninputs: setup - dict object containing setup parameters path - string path to working directory\n\nreturns: Dict (dictionary) object containing all data inputs\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Fuels-Data","page":"Inputs Functions","title":"Fuels Data","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_fuels_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_fuels_data!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_fuels_data!","text":"load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to fuel costs and CO_2 content of fuels\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Generators-Input-Data","page":"Inputs Functions","title":"Generators Input Data","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_resources_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX._get_policyfile_info-Tuple{}","page":"Inputs Functions","title":"GenX._get_policyfile_info","text":"_get_policyfile_info()\n\nInternal function to get policy file information.\n\nReturns\n\npolicyfile_info (NamedTuple): A tuple containing policy file information.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX._get_resource_info-Tuple{}","page":"Inputs Functions","title":"GenX._get_resource_info","text":"_get_resource_info()\n\nInternal function to get resource information (filename and GenX type) for each type of resource available in GenX.\n\n\n\nresource_info (NamedTuple): A tuple containing resource information.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX._get_summary_map-Tuple{}","page":"Inputs Functions","title":"GenX._get_summary_map","text":"_get_summary_map()\n\nInternal function to get a map of GenX resource type their corresponding names in the summary table.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_attributes_to_resource!-Union{Tuple{T}, Tuple{GenX.AbstractResource, Vector{Symbol}, T}} where T<:DataFrames.DataFrameRow","page":"Inputs Functions","title":"GenX.add_attributes_to_resource!","text":"add_attributes_to_resource!(resource::AbstractResource, new_symbols::Vector{Symbol}, new_values::T) where T <: DataFrameRow\n\nAdds a set of new attributes (names and corresponding values) to a resource. The resource is modified in-place.\n\nArguments\n\nresource::AbstractResource: The resource to add attributes to.\nnew_symbols::Vector{Symbol}: Vector of symbols containing the names of the new attributes.\nnew_values::DataFrameRow: DataFrameRow containing the values of the new attributes.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_df_to_resources!-Tuple{Vector{var\"#s4\"} where var\"#s4\"<:GenX.AbstractResource, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.add_df_to_resources!","text":"add_df_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)\n\nAdds the data contained in a DataFrame to a vector of resources. Each row in the DataFrame corresponds to a resource. If the name of the resource in the DataFrame matches a name of a resource in the model, all the columns of that DataFrameRow are added as new attributes to the corresponding resource. \n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\nmodule_in::DataFrame: The dataframe to add.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_id_to_resource_df!-Tuple{DataFrames.DataFrame, AbstractVector{T} where T}","page":"Inputs Functions","title":"GenX.add_id_to_resource_df!","text":"add_id_to_resource_df!(df::DataFrame, indices::AbstractVector)\n\nAdds a new column 'id' to the DataFrame with the provided resource indices. The dataframe is modified in-place.\n\nArguments\n\ndf::DataFrame: The input DataFrame to which the indices are to be added.\nindices::AbstractVector: The array of indices to be added as a new column.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_module_to_resources!-Tuple{Vector{var\"#s267\"} where var\"#s267\"<:GenX.AbstractResource, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.add_module_to_resources!","text":"add_module_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)\n\nReads module dataframe and adds columns as new attributes to the resources in the model if the resource name in the module file matches a resource name in the model. The module file is assumed to have a column named \"resource\" containing the resource names.\n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\nmodule_in::DataFrame: The dataframe with the columns to add to the resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_modules_to_resources!-Tuple{Vector{var\"#s267\"} where var\"#s267\"<:GenX.AbstractResource, Dict, AbstractString}","page":"Inputs Functions","title":"GenX.add_modules_to_resources!","text":"add_modules_to_resources!(resources::Vector{<:AbstractResource}, setup::Dict, resources_path::AbstractString)\n\nReads module dataframes, loops over files and adds columns as new attributes to the resources in the model.\n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\nsetup (Dict): A dictionary containing GenX settings.\nresources_path::AbstractString: The path to the resources folder.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_policies_to_resources!-Tuple{Vector{var\"#s2\"} where var\"#s2\"<:GenX.AbstractResource, AbstractString}","page":"Inputs Functions","title":"GenX.add_policies_to_resources!","text":"add_policies_to_resources!(resources::Vector{<:AbstractResource}, resources_path::AbstractString)\n\nReads policy files and adds policies-related attributes to resources in the model.\n\nArguments\n\nresources::Vector{<:AbstractResource}: Vector of resources in the model.\nresources_path::AbstractString: The path to the resources folder.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_policy_to_resources!-Tuple{Vector{var\"#s7\"} where var\"#s7\"<:GenX.AbstractResource, AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.add_policy_to_resources!","text":"add_policy_to_resources!(resources::Vector{<:AbstractResource}, path::AbstractString, filename::AbstractString)\n\nLoads a single policy file and adds the columns as new attributes to resources in the model if the resource name in the policy file matches a resource name in the model. The policy file is assumed to have a column named \"resource\" containing the resource names.\n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\npath::AbstractString: The path to the policy file.\nfilename::AbstractString: The name of the policy file.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_resources_to_input_data!-Tuple{Dict, Dict, AbstractString, Vector{var\"#s4\"} where var\"#s4\"<:GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.add_resources_to_input_data!","text":"add_resources_to_input_data!(inputs::Dict, setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource})\n\nAdds resources to the inputs Dict with the key \"RESOURCES\" together with sevaral sets of resource indices that are used inside GenX to construct the optimization problem. The inputs Dict is modified in-place.\n\nArguments\n\ninputs (Dict): Dictionary to store the GenX input data.\nsetup (Dict): Dictionary containing GenX settings.\ncase_path (AbstractString): Path to the case.\ngen (Vector{<:AbstractResource}): Array of GenX resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.check_mustrun_reserve_contribution-Tuple{GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.check_mustrun_reserve_contribution","text":"check_mustrun_reserve_contribution(r::AbstractResource)\n\nMake sure that a MUSTRUN resource has RegMax and Rsv_Max set to 0 (since they cannot contribute to reserves).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.check_resource-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Inputs Functions","title":"GenX.check_resource","text":"check_resource(resources::Vector{T})::Vector{String} where T <: AbstractResource\n\nValidate the consistency of a vector of GenX resources Reports any errors/warnings as a vector of messages.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.compute_resource_indices-Tuple{DataFrames.DataFrame, Int64}","page":"Inputs Functions","title":"GenX.compute_resource_indices","text":"compute_resource_indices(resources_in::DataFrame, offset::Int64)\n\nComputes the indices for the resources loaded from a single dataframe by shifting the indices by an offset value. \n\nArguments\n\nresources_in::DataFrame: The input DataFrame containing the resources.\noffset::Int64: The offset value to be added to the indices.\n\nReturns\n\nUnitRange{Int64}: An array of indices.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.create_resource_array","page":"Inputs Functions","title":"GenX.create_resource_array","text":"create_resource_array(resource_folder::AbstractString, resources_info::NamedTuple, scale_factor::Float64=1.0)\n\nConstruct the array of resources from multiple files of different types located in the specified resource_folder. The resources_info NamedTuple contains the filename and GenX type for each type of resource available in GenX.\n\nArguments\n\nresource_folder::AbstractString: The path to the folder containing the resource files.\nresources_info::NamedTuple: A NamedTuple that maps a resource type to its filename and GenX type.\nscale_factor::Float64: A scaling factor to adjust the attributes of the resources (default: 1.0).\n\nReturns\n\nVector{<:AbstractResource}: An array of GenX resources.\n\nRaises\n\nError: If no resources data is found. Check the data path or the configuration file \"genx_settings.yml\" inside Settings.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/load_inputs/#GenX.create_resource_array-Tuple{Dict, AbstractString}","page":"Inputs Functions","title":"GenX.create_resource_array","text":"create_resource_array(setup::Dict, resources_path::AbstractString)\n\nFunction that loads and scales resources data from folder specified in resources_path and returns an array of GenX resources.\n\nArguments\n\nsetup (Dict): Dictionary containing GenX settings.\nresources_path (AbstractString): The path to the resources folder.\n\nReturns\n\nresources (Vector{<:AbstractResource}): An array of scaled resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.create_resources_sametype-Tuple{DataFrames.DataFrame, Any}","page":"Inputs Functions","title":"GenX.create_resources_sametype","text":"create_resources_sametype(resource_in::DataFrame, ResourceType)\n\nThis function takes a DataFrame resource_in and a GenX ResourceType type, and converts the DataFrame to an array of AbstractResource of the specified type.\n\nArguments\n\nresource_in::DataFrame: The input DataFrame containing the resources belonging to a specific type.\nResourceType: The GenX type of resources to be converted to.\n\nReturns\n\nresources::Vector{ResourceType}: An array of resources of the specified type.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.dataframerow_to_dict-Tuple{DataFrames.DataFrameRow}","page":"Inputs Functions","title":"GenX.dataframerow_to_dict","text":"dataframerow_to_dict(dfr::DataFrameRow)\n\nConverts a DataFrameRow to a Dict.\n\nArguments\n\ndfr::DataFrameRow: The DataFrameRow to be converted.\n\nReturns\n\nDict: Dictionary containing the DataFrameRow data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_multi_fuels_data!-Tuple{Dict, Vector{var\"#s4\"} where var\"#s4\"<:GenX.AbstractResource, Dict, AbstractString}","page":"Inputs Functions","title":"GenX.load_multi_fuels_data!","text":"load_multi_fuels_data!(inputs::Dict, gen::Vector{<:AbstractResource}, setup::Dict, path::AbstractString)\n\nFunction for reading input parameters related to multi fuels\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_resource_df-Tuple{AbstractString, Float64, Type}","page":"Inputs Functions","title":"GenX.load_resource_df","text":"load_resource_df(path::AbstractString, scale_factor::Float64, resource_type::Type)\n\nFunction to load and scale the dataframe of a given resource.\n\nArguments\n\npath::AbstractString: Path to the resource dataframe.\nscale_factor::Float64: Scaling factor for the resource data.\nresource_type::Type: GenX type of the resource.\n\nReturns\n\nresource_in::DataFrame: The loaded and scaled resource data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_resources_data!-Tuple{Dict, Dict, AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.load_resources_data!","text":"load_resources_data!(inputs::Dict, setup::Dict, case_path::AbstractString, resources_path::AbstractString)\n\nThis function loads resources data from the resources_path folder and create the GenX data structures and add them to the inputs Dict. \n\nArguments\n\ninputs (Dict): A dictionary to store the input data.\nsetup (Dict): A dictionary containing GenX settings.\ncase_path (AbstractString): The path to the case folder.\nresources_path (AbstractString): The path to the case resources folder.\n\nRaises: DeprecationWarning: If the Generators_data.csv file is found, a deprecation warning is issued, together with an error message.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.process_piecewisefuelusage!-Tuple{Dict, Vector{var\"#s3\"} where var\"#s3\"<:GenX.AbstractResource, Dict}","page":"Inputs Functions","title":"GenX.process_piecewisefuelusage!","text":"process_piecewisefuelusage!(setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource}, inputs::Dict)\n\nReads piecewise fuel usage data from the vector of generators, create a PWFU_data that contain processed intercept and slope (i.e., heat rate) and add them to the inputs dictionary. \n\nArguments\n\nsetup::Dict: The dictionary containing the setup parameters\ncase_path::AbstractString: The path to the case folder\ngen::Vector{<:AbstractResource}: The vector of generators in the model\ninputs::Dict: The dictionary containing the input data\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.scale_columns!-Tuple{DataFrames.DataFrame, Vector{Symbol}, Float64}","page":"Inputs Functions","title":"GenX.scale_columns!","text":"scale_columns!(df::DataFrame, columns_to_scale::Vector{Symbol}, scale_factor::Float64)\n\nScales in-place the columns in columns_to_scale of a dataframe df by a scale_factor.\n\nArguments\n\ndf (DataFrame): A dataframe containing data to scale.\ncolumns_to_scale (Vector{Symbol}): A vector of column names to scale.\nscale_factor (Float64): A scaling factor for energy and currency units.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.scale_resources_data!-Tuple{DataFrames.DataFrame, Float64}","page":"Inputs Functions","title":"GenX.scale_resources_data!","text":"scale_resources_data!(resource_in::DataFrame, scale_factor::Float64)\n\nScales resources attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.\n\nArguments\n\nresource_in (DataFrame): A dataframe containing data for a specific resource.\nscale_factor (Float64): A scaling factor for energy and currency units.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.scale_vre_stor_data!-Tuple{DataFrames.DataFrame, Float64}","page":"Inputs Functions","title":"GenX.scale_vre_stor_data!","text":"scale_vre_stor_data!(vre_stor_in::DataFrame, scale_factor::Float64)\n\nScales vre_stor attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.\n\nArguments\n\nvre_stor_in (DataFrame): A dataframe containing data for co-located VREs and storage.\nscale_factor (Float64): A scaling factor for energy and currency units.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.split_storage_resources!-Tuple{Dict, Vector{var\"#s267\"} where var\"#s267\"<:GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.split_storage_resources!","text":"split_storage_resources!(inputs::Dict, gen::Vector{<:AbstractResource})\n\nFor co-located VRE-storage resources, this function returns the storage type \t(1. long-duration or short-duration storage, 2. symmetric or asymmetric storage) for charging and discharging capacities\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.summary-Tuple{Vector{var\"#s7\"} where var\"#s7\"<:GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.summary","text":"summary(rs::Vector{<:AbstractResource})\n\nPrints a summary of the resources loaded into the model.\n\nArguments\n\nrs (Vector{<:AbstractResource}): An array of GenX resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.update_retrofit_id-Tuple{GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.update_retrofit_id","text":"update_retrofit_id(r::AbstractResource)\n\nUpdates the retrofitid of a resource that can be retrofit or is a retrofit option by appending the region to the retrofitid.\n\nArguments\n\nr::AbstractResource: The resource to update.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.validate_policy_dataframe!-Tuple{AbstractString, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.validate_policy_dataframe!","text":"validate_policy_dataframe!(filename::AbstractString, policy_in::DataFrame)\n\nValidate the policy dataframe by checking if it has any attributes and if the column names are valid. The dataframe is modified in-place.\n\nArguments\n\nfilename::AbstractString: The name of the policy file.\npolicy_in::DataFrame: The policy dataframe.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.validate_policy_files-Tuple{AbstractString, Dict}","page":"Inputs Functions","title":"GenX.validate_policy_files","text":"validate_policy_files(resource_policies_path::AbstractString, setup::Dict)\n\nValidate the policy files by checking if they exist in the specified folder and if the setup flags are consistent with the files found.\n\nArguments\n\nresource_policies_path::AbstractString: The path to the policy files.\nsetup::Dict: Dictionary containing GenX settings.\n\nReturns\n\nwarning messages if the polcies are set to 1 in settings but the files are not found in the resourcepoliciespath.\n\n!isfile(joinpath(resourcepoliciespath, filename))\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Variability-of-Generators'-Outputs","page":"Inputs Functions","title":"Variability of Generators' Outputs","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_generators_variability.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_generators_variability!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_generators_variability!","text":"load_generators_variability!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to hourly maximum capacity factors for generators, storage, and flexible demand resources\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Demand-Data","page":"Inputs Functions","title":"Demand Data","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_demand_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_demand_data!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_demand_data!","text":"load_demand_data!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to electricity demand (load)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.prevent_doubled_timedomainreduction-Tuple{AbstractString}","page":"Inputs Functions","title":"GenX.prevent_doubled_timedomainreduction","text":"prevent_doubled_timedomainreduction(path::AbstractString)\n\nThis function prevents TimeDomainReduction from running on a case which already has more than one Representative Period or has more than one Sub_Weight specified.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Transmission-Network","page":"Inputs Functions","title":"Transmission Network","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_network_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_network_data!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_network_data!","text":"load_network_data!(setup::Dict, path::AbstractString, inputs_nw::Dict)\n\nFunction for reading input parameters related to the electricity transmission network\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_network_map_from_list-Tuple{DataFrames.DataFrame, Any, Any, Any}","page":"Inputs Functions","title":"GenX.load_network_map_from_list","text":"load_network_map_from_list(network_var::DataFrame, Z, L, list_columns)\n\nLoads the network map from a list-style interface\n\n..., Network_Lines, Start_Zone, End_Zone, ...\n 1, 1, 2,\n 2, 1, 3,\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_network_map_from_matrix-Tuple{DataFrames.DataFrame, Any, Any}","page":"Inputs Functions","title":"GenX.load_network_map_from_matrix","text":"load_network_map_from_matrix(network_var::DataFrame, Z, L)\n\nLoads the network map from a matrix-style interface\n\n..., Network_Lines, z1, z2, z3, ...\n 1, 1, -1, 0,\n 2, 1, 0, -1,\n\nThis is equivalent to the list-style interface where the zone zN with entry +1 is the starting zone of the line and the zone with entry -1 is the ending zone of the line.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Minimum-Capacity-Requirements","page":"Inputs Functions","title":"Minimum Capacity Requirements","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_minimum_capacity_requirement.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_minimum_capacity_requirement!-Tuple{AbstractString, Dict, Dict}","page":"Inputs Functions","title":"GenX.load_minimum_capacity_requirement!","text":"load_minimum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)\n\nRead input parameters related to mimimum capacity requirement constraints (e.g. technology specific deployment mandates)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Capacity-Reserve-Margin","page":"Inputs Functions","title":"Capacity Reserve Margin","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_cap_reserve_margin.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_cap_reserve_margin!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_cap_reserve_margin!","text":"load_cap_reserve_margin!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to planning reserve margin constraints\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_cap_reserve_margin_trans!-Tuple{Dict, Dict, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.load_cap_reserve_margin_trans!","text":"load_cap_reserve_margin_trans!(setup::Dict, inputs::Dict, network_var::DataFrame)\n\nRead input parameters related to participation of transmission imports/exports in capacity reserve margin constraint.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#CO_2-Emissions-Cap","page":"Inputs Functions","title":"CO_2 Emissions Cap","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_co2_cap.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_co2_cap!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_co2_cap!","text":"load_co2_cap!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to CO_2 emissions cap constraints\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Energy-Share-Requirement","page":"Inputs Functions","title":"Energy Share Requirement","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_energy_share_requirement.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_energy_share_requirement!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_energy_share_requirement!","text":"load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Mapping-Representative-Time-Periods","page":"Inputs Functions","title":"Mapping Representative Time Periods","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_period_map.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_period_map!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_period_map!","text":"load_period_map!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to mapping of representative time periods to full chronological time series\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Variability-of-the-Solar-PV-and-Wind-Components'-Outputs-(for-Co-located-Storage-Resources)","page":"Inputs Functions","title":"Variability of the Solar PV and Wind Components' Outputs (for Co-located Storage Resources)","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_vre_stor_variability.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_vre_stor_variability!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_vre_stor_variability!","text":"load_vre_stor_variability!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to hourly maximum capacity factors for the solar PV \t(DC capacity factors) component and wind (AC capacity factors) component of co-located \tgenerators\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Functions-for-developers","page":"Inputs Functions","title":"Functions for developers","text":"","category":"section"},{"location":"Model_Reference/load_inputs/#Standardized-loading-of-dataframes-from-CSV-files","page":"Inputs Functions","title":"Standardized loading of dataframes from CSV files","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_dataframe.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.extract_matrix_from_dataframe-Tuple{DataFrames.DataFrame, AbstractString}","page":"Inputs Functions","title":"GenX.extract_matrix_from_dataframe","text":"extract_matrix_from_dataframe(df::DataFrame, columnprefix::AbstractString)\n\nFinds all columns in the dataframe which are of the form columnprefix_[Integer], and extracts them in order into a matrix. The function also checks that there's at least one column with this prefix, and that all columns numbered from 1...N exist.\n\nThis is now acceptable:\n\nESR_1, other_thing, ESR_3, ESR_2,\n 0.1, 1, 0.3, 0.2,\n 0.4, 2, 0.6, 0.5,\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.file_exists-Tuple{Any, Vector{String}}","page":"Inputs Functions","title":"GenX.file_exists","text":"file_exists(dir::AbstractString, basenames::Vector{String})::Bool\n\nChecks that a file exists in a directory under (at least) one of a list of 'aliases'.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_dataframe-Tuple{AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.load_dataframe","text":"load_dataframe(dir::AbstractString, base::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_dataframe-Tuple{AbstractString}","page":"Inputs Functions","title":"GenX.load_dataframe","text":"load_dataframe(path::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.validate_df_cols-Tuple{DataFrames.DataFrame, AbstractString, Any}","page":"Inputs Functions","title":"GenX.validate_df_cols","text":"validate_df_cols(df::DataFrame, df_name::AbstractString, required_cols::Vector{AbstractString})\n\nCheck that the dataframe has all the required columns.\n\nArguments\n\ndf::DataFrame: the dataframe to check\ndf_name::AbstractString: the name of the dataframe, for error messages\nrequired_cols::Vector{AbstractString}: the names of the required columns\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/electrolyzers/#Hydrogen-Electrolyzers","page":"Hydrogen Electrolyzers","title":"Hydrogen Electrolyzers","text":"","category":"section"},{"location":"Model_Reference/Resources/electrolyzers/","page":"Hydrogen Electrolyzers","title":"Hydrogen Electrolyzers","text":"Modules = [GenX]\nPages = [\"electrolyzer.jl\"]","category":"page"},{"location":"Model_Reference/Resources/electrolyzers/#GenX.electrolyzer!-Tuple{JuMP.Model, Dict, Dict}","page":"Hydrogen Electrolyzers","title":"GenX.electrolyzer!","text":"electrolyzer!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the expressions and constraints for operation of hydrogen electrolyzers (y in mathcalEL subseteq mathcalG). \tThis is a basic implementation of hydrogen electrolyzers that allows the specification of an hourly clean supply constraint. \tFor a richer formulation, please see the DOLPHYN code at https://github.com/macroenergy/DOLPHYN.\n\nExpressions\n\nConsumption of electricity by electrolyzer y in time t, denoted by Pi_yz, is subtracted from power balance expression ePowerBalance (as per other demands or battery charging) and added to Energy Share Requirement policy balance (if applicable), eESR.\n\nRevenue from hydrogen production by each electrolyzer y, equal to omega_t times Pi_yt eta^electrolyzer_y times ^{hydrogen}y$, is subtracted from the objective function, where \\eta^{electrolyzer}y$ is the efficiency of the electrolyzer y in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced and ^{hydrogen}_y$ is the price of hydrogen per metric tonne for electrolyzer y.\n\nRamping limits\n\nElectrolyzers adhere to the following ramping limits on hourly changes in power output:\n\nbeginaligned\n\tPi_yt-1 - Pi_yt leq kappa_y^down Delta^texttotal_y hspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\nbeginaligned\n\tPi_yt - Pi_yt-1 leq kappa_y^up Delta^texttotal_y hspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\n(See Constraints 1-2 in the code)\n\nThis set of time-coupling constraints wrap around to ensure the power output in the first time step of each year (or each representative period), t in mathcalT^start, is within the eligible ramp of the power output in the final time step of the year (or each representative period), t+tau^period-1.\n\nMinimum and maximum power output\n\nElectrolyzers are bound by the following limits on maximum and minimum power output:\n\nbeginaligned\n\tPi_yt geq rho^min_y times Delta^total_y\n\thspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yt leq rho^max_yt times Pi_^total_y\n\thspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\n(See Constraints 3-4 in the code)\n\nMinimum annual hydrogen production\n\nThe sum of annual hydrogen production by each electrolyzer y in mathcalEL must exceed a minimum quantity specified in inputs:\n\nbeginaligned\n\tsum_t in T (omega_t times Pi_yt eta^electrolyzer_y) geq mathcalMin kt_y times 10^3\n\thspace1cm forall y in mathcalEL\nendaligned\n\nwhere eta^electrolyzer_y is the efficiency of the electrolyzer y in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced and mathcalMin kt_y is the minimum annual quantity of hydrogen that must be produced by electrolyzer y in kilotonnes. (See constraint 5 in the code)\n\nHourly clean supply matching constraint\n\nThis optional constraint (enabled by setting HydrogenHourlyMatching==1 in genx_settings.yml) requires generation from qualified resources (y in mathcalQualified, indicated by Qualified_Hydrogen_Supply==1 in the resource .csv files) from within the same zone z as the electrolyzers are located to be >= hourly consumption from electrolyzers in the zone (and any charging by qualified storage within the zone used to help increase electrolyzer utilization):\n\nbeginaligned\n\tsum_y in z cap mathcalQualified Theta_yt geq sum_y in z cap mathcalEL Pi_yt + sum_y in z cap mathcalQualified cap mathcalSTOR Pi_yt\n\thspace1cm forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See constraint 6 in the code)\n\nThis constraint permits modeling of the 'three pillars' requirements for clean hydrogen supply of (1) new clean supply (if only new clean resources are designated as eligible), (2) that is deliverable to the electrolyzer (assuming co-location within the same modeled zone = deliverability), and (3) produced within the same hour as the electrolyzer consumes power (otherwise known as 'additionality/new supply', 'deliverability', and 'temporal matching requirements') See Ricks, Xu & Jenkins (2023), ''Minimizing emissions from grid-based hydrogen production in the United States'' Environ. Res. Lett. 18 014025 doi:10.1088/1748-9326/acacb5 for more.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Core","page":"Core","title":"Core","text":"","category":"section"},{"location":"Model_Reference/core/#Discharge","page":"Core","title":"Discharge","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"discharge.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.discharge!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.discharge!","text":"discharge!(EP::Model, inputs::Dict, setup::Dict)\n\nThis module defines the power decision variable Theta_yt forall y in mathcalG t in mathcalT, representing energy injected into the grid by resource y by at time period t. This module additionally defines contributions to the objective function from variable costs of generation (variable O&M) from all resources y in mathcalG over all time periods t in mathcalT:\n\nbeginaligned\n\tObj_Var_gen =\n\tsum_y in mathcalG sum_t in mathcalTomega_ttimes(pi^VOM_y)times Theta_yt\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.investment_discharge!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.investment_discharge!","text":"investment_discharge!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the expressions and constraints keeping track of total available power generation/discharge capacity across all resources as well as constraints on capacity retirements. The total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity. Note for storage and co-located resources, additional energy and charge power capacity decisions and constraints are defined in the storage and co-located VRE and storage module respectively.\n\nbeginaligned\n Delta^total_yz =(overlineDelta_yz+Omega_yz-Delta_yz) forall y in mathcalG z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity.\n\nbeginaligned\nDelta_yz leq overlineDelta_yz\n\thspace4 cm forall y in mathcalG z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz and underlineOmega_yz is defined, then we impose constraints on minimum and maximum power capacity.\n\nbeginaligned\n Delta^total_yz leq overlineOmega_yz\n\thspace4 cm forall y in mathcalG z in mathcalZ \n Delta^total_yz geq underlineOmega_yz\n\thspace4 cm forall y in mathcalG z in mathcalZ\nendaligned\n\nIn addition, this function adds investment and fixed O\\&M related costs related to discharge/generation capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalG sum_z in mathcalZ\n\tleft( (pi^INVEST_yz times overlineOmega^size_yz times Omega_yz)\n\t+ (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.write_multi_stage_capacities_discharge-Tuple{String, Dict}","page":"Core","title":"GenX.write_multi_stage_capacities_discharge","text":"write_multi_stage_capacities_discharge(outpath::String, settings_d::Dict)\n\nThis function writes the file capacities_multi_stage.csv to the Results directory. This file contains starting resource capacities from the first model stage and end resource capacities for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.write_virtual_discharge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Core","title":"GenX.write_virtual_discharge","text":"write_virtual_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the \"virtual\" discharge of each storage technology. Virtual discharge is used to \tallow storage resources to contribute to the capacity reserve margin without actually discharging.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Non-served-Energy","page":"Core","title":"Non-served Energy","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"non_served_energy.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.non_served_energy!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.non_served_energy!","text":"non_served_energy!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the non-served energy/curtailed demand decision variable Lambda_stz forall s in mathcalS forall t in mathcalT z in mathcalZ, representing the total amount of demand curtailed in demand segment s at time period t in zone z. The first segment of non-served energy, s=1, is used to denote the cost of involuntary demand curtailment (e.g. emergency load shedding or rolling blackouts), specified as the value of n_1^slope. Additional segments, s geq 2 can be used to specify a segment-wise approximation of a price elastic demand curve, or segments of price-responsive curtailable demands (aka demand response). Each segment denotes a price/cost at which the segment of demand is willing to curtail consumption, n_s^slope, representing the marginal willingness to pay for electricity of this segment of demand (or opportunity cost incurred when demand is not served) and a maximum quantity of demand in this segment, n_s^size, specified as a share of demand in each zone in each time step, D_tz Note that the current implementation assumes demand segments are an equal share of hourly demand in all zones. This function defines contributions to the objective function from the cost of non-served energy/curtailed demand from all demand curtailment segments s in mathcalS over all time periods t in mathcalT and all zones z in mathcalZ:\n\nbeginaligned\n\tObj_NSE =\n\tsum_s in mathcalS sum_t in mathcalT sum_z in mathcalZomega_t times n_s^slope times Lambda_stz\nendaligned\n\nContributions to the power balance expression from non-served energy/curtailed demand from each demand segment s in mathcalS are also defined as:\n\nbeginaligned\n\tPowerBal_NSE =\n\tsum_s in mathcalS Lambda_stz\n\t\thspace4 cm forall s in mathcalS t in mathcalT\nendaligned\n\nBounds on curtailable demand Demand curtailed in each segment of curtailable demands s in mathcalS cannot exceed a maximum allowable share of demand:\n\nbeginaligned\n\tLambda_stz leq (n_s^size times D_tz)\n\thspace4 cm forall s in mathcalS t in mathcalT zin mathcalZ\nendaligned\n\nAdditionally, total demand curtailed in each time step cannot exceed total demand:\n\nbeginaligned\n\tsum_s in mathcalS Lambda_stz leq D_tz\n\thspace4 cm forall t in mathcalT zin mathcalZ\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Operational-Reserves","page":"Core","title":"Operational Reserves","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"operational_reserves.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.load_operational_reserves!-Tuple{Dict, AbstractString, Dict}","page":"Core","title":"GenX.load_operational_reserves!","text":"load_operational_reserves!(setup::Dict,path::AbstractString, inputs::Dict)\n\nRead input parameters related to frequency regulation and operating reserve requirements\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.operational_reserves!","text":"operational_reserves!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function sets up reserve decisions and constraints, using the operationalreservescore()and operational_reserves_contingency() functions.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.operational_reserves_contingency!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.operational_reserves_contingency!","text":"operational_reserves_contingency!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function establishes several different versions of contingency reserve requirement expression, CONTINGENCY used in the operationalreservescore() function below.\n\nContingency operational reserves represent requirements for upward ramping capability within a specified time frame to compensated for forced outages or unplanned failures of generators or transmission lines (e.g. N-1 contingencies).\n\nThere are three options for the Contingency expression, depending on user settings: \t1. a static contingency, in which the contingency requirement is set based on a fixed value (in MW) specified in the '''Operational_reserves.csv''' input file; \t2. a dynamic contingency based on installed capacity decisions, in which the largest 'installed' generator is used to determine the contingency requirement for all time periods; and \t3. dynamic unit commitment based contingency, in which the largest 'committed' generator in any time period is used to determine the contingency requirement in that time period.\n\nNote that the two dynamic contigencies are only available if unit commitment is being modeled.\n\nStatic contingency Option 1 (static contingency) is expressed by the following constraint:\n\nbeginaligned\n\tContingency = epsilon^contingency\nendaligned\n\nwhere epsilon^contingency is static contingency requirement in MWs.\n\nDynamic capacity-based contingency Option 2 (dynamic capacity-based contingency) is expressed by the following constraints:\n\nbeginaligned\n\tContingency geq Omega^size_yz times alpha^ContingencyAux_yz forall y in mathcalUC z in mathcalZ\n\talpha^ContingencyAux_yz leq Delta^texttotal_yz forall y in mathcalUC z in mathcalZ\n\talpha^ContingencyAux_yz geq M_y times Delta^texttotal_yz forall y in mathcalUC z in mathcalZ\nendaligned\n\nwhere M_y is a `big M' constant equal to the largest possible capacity that can be installed for generation cluster y, and alpha^ContingencyAux_yz in 01 is a binary auxiliary variable that is forced by the second and third equations above to be 1 if the total installed capacity Delta^texttotal_yz 0 for any generator y in mathcalUC and zone z, and can be 0 otherwise. Note that if the user specifies contingency option 2, and is also using the linear relaxation of unit commitment constraints, the capacity size parameter for units in the set mathcalUC must still be set to a discrete unit size for this contingency to work as intended.\n\nDynamic commitment-based contingency Option 3 (dynamic commitment-based contingency) is expressed by the following set of constraints:\n\nbeginaligned\n\t Contingency geq Omega^size_yz times Contingency_Aux_yzt forall y in mathcalUC z in mathcalZ\n\t Contingency_Aux_yzt leq nu_yzt forall y in mathcalUC z in mathcalZ\n\t Contingency_Aux_yzt geq M_y times nu_yzt forall y in mathcalUC z in mathcalZ\nendaligned\n\nwhere M_y is a `big M' constant equal to the largest possible capacity that can be installed for generation cluster y, and Contingency_Aux_yzt in 01 is a binary auxiliary variable that is forced by the second and third equations above to be 1 if the commitment state for that generation cluster nu_yzt 0 for any generator y in mathcalUC and zone z and time period t, and can be 0 otherwise. Note that this dynamic commitment-based contingency can only be specified if discrete unit commitment decisions are used (e.g. it will not work if relaxed unit commitment is used).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.operational_reserves_core!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.operational_reserves_core!","text":"operational_reserves_core!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates decision variables related to frequency regulation and reserves provision and constraints setting overall system requirements for regulation and operating reserves.\n\nRegulation and reserves decisions f_ytz geq 0 is the contribution of generation or storage resource y in Y in time t in T and zone z in Z to frequency regulation\n\nr_ytz geq 0\n\nis the contribution of generation or storage resource y in Y in time t in T and zone z in Z to operating reserves up\n\nWe assume frequency regulation is symmetric (provided in equal quantity towards both upwards and downwards regulation). To reduce computational complexity, operating reserves are only modeled in the upwards direction, as downwards reserves requirements are rarely binding in practice.\n\nStorage resources (y in mathcalO) have two pairs of auxilary variables to reflect contributions to regulation and reserves when charging and discharging, where the primary variables (f_yzt \\& r_yzt) becomes equal to sum of these auxilary variables.\n\nCo-located VRE-STOR resources are described further in the reserves function for colocated VRE and storage resources (vre_stor_operational_reserves!()).\n\nUnmet operating reserves\n\nunmet_rsv_t geq 0\n\ndenotes any shortfall in provision of operating reserves during each time period t in T\n\nThere is a penalty C^rsv added to the objective function to penalize reserve shortfalls, equal to:\n\nbeginaligned\n\tC^rvs = sum_t in T omega_t times unmet_rsv_t\nendaligned\n\nFrequency regulation requirements\n\nTotal requirements for frequency regulation (aka primary reserves) in each time step t are specified as fractions of hourly demand (to reflect demand forecast errors) and variable renewable avaialblity in the time step (to reflect wind and solar forecast errors).\n\nbeginaligned\n sum_y in Y z in Z f_ytz geq epsilon^demand_reg times sum_z in Z mathcalD_zt + epsilon^vre_reg times (sum_z in Z rho^max_yzt times Delta^texttotal_yz \n + sum_z in Z rho^maxpv_yzt times Delta^texttotalpv_yz + sum_z in Z rho^maxwind_yzt times Delta^texttotalwind_yz) quad forall t in T\nendaligned\n\nwhere mathcalD_zt is the forecasted electricity demand in zone z at time t (before any demand flexibility); rho^max_yzt is the forecasted capacity factor for standalone variable renewable resources y in VRE and zone z in time step t; rho^maxpv_yzt is the forecasted capacity factor for co-located solar PV resources y in mathcalVS^pv and zone z in time step t; rho^maxwind_yzt is the forecasted capacity factor for co-located wind resources y in mathcalVS^pv and zone z in time step t; Delta^texttotalpv_yz is the total installed capacity of co-located solar PV resources y in mathcalVS^pv and zone z; Delta^texttotalwind_yz is the total installed capacity of co-located wind resources y in mathcalVS^wind and zone z; and epsilon^demand_reg and epsilon^vre_reg are parameters specifying the required frequency regulation as a fraction of forecasted demand and variable renewable generation.\n\nOperating reserve requirements\n\nTotal requirements for operating reserves in the upward direction (aka spinning reserves or contingency reserces or secondary reserves) in each time step t are specified as fractions of time step's demand (to reflect demand forecast errors) and variable renewable avaialblity in the time step (to reflect wind and solar forecast errors) plus the largest planning contingency (e.g. potential forced generation outage).\n\nbeginaligned\n\t sum_y in Y z in Z r_yzt + r^unmet_t geq epsilon^demand_rsv times sum_z in Z mathcalD_zt + epsilon^vre_rsv times (sum_z in Z rho^max_yzt times Delta^texttotal_yz \n\t + sum_z in Z rho^maxpv_yzt times Delta^texttotalpv_yz + sum_z in Z rho^maxwind_yzt times Delta^texttotalwind_yz) + Contingency quad forall t in T\nendaligned\n\nwhere mathcalD_zt is the forecasted electricity demand in zone z at time t (before any demand flexibility); rho^max_yzt is the forecasted capacity factor for standalone variable renewable resources y in VRE and zone z in time step t; rho^maxpv_yzt is the forecasted capacity factor for co-located solar PV resources y in mathcalVS^pv and zone z in time step t; rho^maxwind_yzt is the forecasted capacity factor for co-located wind resources y in mathcalVS^wind and zone z in time step t; Delta^texttotal_yz is the total installed capacity of standalone variable renewable resources y in VRE and zone z; Delta^texttotalpv_yz is the total installed capacity of co-located solar PV resources y in mathcalVS^pv and zone z; Delta^texttotalwind_yz is the total installed capacity of co-located wind resources y in mathcalVS^wind and zone z; and epsilon^demand_rsv and epsilon^vre_rsv are parameters specifying the required contingency reserves as a fraction of forecasted demand and variable renewable generation. Contingency is an expression defined in the operational_reserves_contingency!() function meant to represent the largest N-1 contingency (unplanned generator outage) that the system operator must carry operating reserves to cover and depends on how the user wishes to specify contingency requirements.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Transmission","page":"Core","title":"Transmission","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"transmission.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.dcopf_transmission!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.dcopf_transmission!","text":"function dcopf_transmission!(EP::Model, inputs::Dict, setup::Dict)\n\nThe addtional constraints imposed upon the line flows in the case of DC-OPF are as follows: For the definition of the line flows, in terms of the voltage phase angles:\n\nbeginaligned\n Phi_lt=mathcalB_l times (sum_zin mathcalZ(varphi^map_lz times theta_zt)) quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nFor imposing the constraint of maximum allowed voltage phase angle difference across lines:\n\nbeginaligned\n sum_zin mathcalZ(varphi^map_lz times theta_zt) leq Delta theta^max_l quad forall l in mathcalL forall t in mathcalT\n\t sum_zin mathcalZ(varphi^map_lz times theta_zt) geq -Delta theta^max_l quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nFinally, we enforce the reference voltage phase angle constraint:\n\nbeginaligned\ntheta_1t = 0 quad forall t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.investment_transmission!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.investment_transmission!","text":"function investment_transmission!(EP::Model, inputs::Dict, setup::Dict)\n The function model transmission expansion and adds transmission reinforcement or construction costs to the objective function. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, $pi^{TCAP}_{l}$, times the additional transmission capacity variable, $\\bigtriangleup\\varphi^{cap}_{l}$.\n ```math\n \\begin{aligned}\n & \\sum_{l \\in \\mathcal{L}}\\left(\\pi^{TCAP}_{l} \\times \\bigtriangleup\\varphi^{cap}_{l}\\right)\n \\end{aligned}\n ```\n Note that fixed O\\&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.\n **Accounting for Transmission Between Zones**\n Available transmission capacity between zones is set equal to the existing line's maximum power transfer capacity, $\\overline{\\varphi^{cap}_{l}}$, plus any transmission capacity added on that line (for lines eligible for expansion in the set $\\mathcal{E}$). \n \\begin{aligned}\n &\\varphi^{cap}_{l} = \\overline{\\varphi^{cap}_{l}} , &\\quad \\forall l \\in (\\mathcal{L} \\setminus \\mathcal{E} ),\\forall t \\in \\mathcal{T}\\\\\n % trasmission expansion\n &\\varphi^{cap}_{l} = \\overline{\\varphi^{cap}_{l}} + \\bigtriangleup\\varphi^{cap}_{l} , &\\quad \\forall l \\in \\mathcal{E},\\forall t \\in \\mathcal{T} \n \\end{aligned}\n The additional transmission capacity, $\\bigtriangleup\\varphi^{cap}_{l} $, is constrained by a maximum allowed reinforcement, $\\overline{\\bigtriangleup\\varphi^{cap}_{l}}$, for each line $l \\in \\mathcal{E}$.\n \\begin{aligned}\n & \\bigtriangleup\\varphi^{cap}_{l} \\leq \\overline{\\bigtriangleup\\varphi^{cap}_{l}}, &\\quad \\forall l \\in \\mathcal{E}\n \\end{aligned}\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.transmission!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.transmission!","text":"transmission!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function establishes decisions, expressions, and constraints related to transmission power flows between model zones and associated transmission losses (if modeled).\n\nPower flow and transmission loss terms are also added to the power balance constraint for each zone:\n\nbeginaligned\n\t- sum_lin mathcalL(varphi^map_lz times Phi_lt) - frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot))\nendaligned\n\nPower flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign is used for this term. Losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see below). Accounting for Transmission Between Zones Power flow, Phi_lt, on each line (or more likely a `path' aggregating flows across multiple parallel lines) is constrained to be less than or equal to the line's power transfer capacity, varphi^cap_l, plus any transmission capacity added on that line (for lines eligible for expansion in the set mathcalE). The additional transmission capacity, bigtriangleupvarphi^cap_l is constrained by a maximum allowed reinforcement overlinebigtriangleupvarphi^cap_l, for each line l in mathcalE.\n\nbeginaligned\n\t trasmission constraints\n\t-varphi^cap_l leq Phi_lt leq varphi^cap_l quad forall l in mathcalLforall t in mathcalT\nendaligned\n\nAccounting for Transmission Losses Transmission losses due to power flows can be accounted for in three different ways. The first option is to neglect losses entirely, setting the value of the losses function to zero for all lines at all hours. The second option is to assume that losses are a fixed percentage, varphi^loss_l, of the magnitude of power flow on each line, mid Phi_lt mid (e.g., losses are a linear function of power flows). Finally, the third option is to calculate losses, ell_lt, by approximating a quadratic-loss function of power flow across the line using a piecewise-linear function with total number of segments equal to the size of the set mathcalM.\n\nbeginaligned\nconfigurable losses formulation\n\t beta_lt(cdot) = begincases 0 textif textlosses0 varphi^loss_ltimes mid Phi_lt mid textif textlosses1 ell_lt textif textlosses2 endcases quad forall l in mathcalLforall t in mathcalT\nendaligned\n\nFor the second option, an absolute value approximation is utilized to calculate the magnitude of the power flow on each line (reflecting the fact that negative power flows for a line linking nodes i and j represents flows from node j to i and causes the same magnitude of losses as an equal power flow from i to j). This absolute value function is linearized such that the flow in the line must be equal to the subtraction of the auxiliary variable for flow in the positive direction, Phi^+_lt, and the auxiliary variable for flow in the negative direction, Phi^+_lt, of the line. Then, the magnitude of the flow is calculated as the sum of the two auxiliary variables. The sum of positive and negative directional flows are also constrained by the line flow capacity.\n\nbeginaligned\n trasmission losses simple\n\tPhi_lt = Phi^+_lt - Phi^-_lt quad forall l in mathcalL forall t in mathcalT\n\tmid Phi_lt mid = Phi^+_lt + Phi^-_lt quad forall l in mathcalL forall t in mathcalT\n\tPhi^+_lt + Phi^-_lt leq varphi^cap_l quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nIf discrete unit commitment decisions are modeled, ``phantom losses'' can be observed wherein the auxiliary variables for flows in both directions (Phi^+_lt and Phi^-_lt) are both increased to produce increased losses so as to avoid cycling a thermal generator and incurring start-up costs or opportunity costs related to minimum down times. This unrealistic behavior can be eliminated via inclusion of additional constraints and a set of auxiliary binary variables, ON^+_lt in 01 forall l in mathcalL. Then the following additional constraints are created:\n\nbeginaligned\n\tPhi^+_lt leq TransON^+_lt quad forall l in mathcalL forall t in mathcalT\n\tPhi^-_lt leq varphi^cap_l -TransON^+_lt quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nwhere TransON^+_lt is a continuous variable, representing the product of the binary variable ON^+_lt and the expression, varphi^cap_l. This product cannot be defined explicitly, since it will lead to a bilinear expression involving two variables. Instead, we enforce this definition via the Glover's Linearization as shown below (also referred McCormick Envelopes constraints for bilinear expressions, which is exact when one of the variables is binary).\n\nbeginaligned\n\tTransON^+_lt leq (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) times TransON^+_lt quad forall l in mathcalL forall t in mathcalT \n\tTransON^+_lt leq varphi^cap_l quad forall l in mathcalL forall t in mathcalT \n\tTransON^+_lt geq varphi^cap_l - (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) times(1- TransON^+_lt) quad forall l in mathcalL forall t in mathcalT \nendaligned\n\nThese constraints permit only the positive or negative auxiliary flow variables to be non-zero at a given time period, not both. For the third option, losses are calculated as a piecewise-linear approximation of a quadratic function of power flows. In order to do this, we represent the absolute value of the line flow variable by the sum of positive stepwise flow variables (mathcalS^+_mlt mathcalS^-_mlt), associated with each partition of line losses computed using the corresponding linear expressions. This can be understood as a segmentwise linear fitting (or first order approximation) of the quadratic losses function. The first constraint below computes the losses a the accumulated sum of losses for each linear stepwise segment of the approximated quadratic function, including both positive domain and negative domain segments. A second constraint ensures that the stepwise variables do not exceed the maximum size per segment. The slope and maximum size for each segment are calculated as per the method in \\cite{Zhang2013}.\n\nbeginaligned\n\t ell_lt = fracvarphi^ohm_l(varphi^volt_l)^2bigg( sum_m in mathcalM( S^+_mltimes mathcalS^+_mlt + S^-_mltimes mathcalS^-_mlt) bigg) quad forall l in mathcalL forall t in mathcalT \n\t textquad Where \n\t quad S^+_ml = frac2+4 times sqrt2times (m-1)1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) quad forall m in 1 colon M l in mathcalL \n\t quad S^-_ml = frac2+4 times sqrt2times (m-1)1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) quad forall m in 1 colon M l in mathcalL\n\t \n\t mathcalS^+_mlt mathcalS^-_mlt = overlinemathcalS_ml quad forall m in 1M l in mathcalL t in mathcalT \n\t textquad Where \n\t quad overlineS_lz = begincases frac(1+sqrt2)1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) textif m = 1 \n\tfrac2 times sqrt2 1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) textif m 1 endcases\nendaligned\n\nNext, a constraint ensures that the sum of auxiliary segment variables (m geq 1) minus the \"zero\" segment (which allows values to go into the negative domain) from both positive and negative domains must total the actual power flow across the line, and a constraint ensures that the sum of negative and positive flows do not exceed the flow capacity of the line.\n\nbeginaligned\n\tsum_m in 1M (mathcalS^+_mlt) - mathcalS^+_0lt = Phi_lt quad forall l in mathcalL forall t in mathcalT\n\tsum_m in 1M (mathcalS^-_mlt) - mathcalS^-_0lt = - Phi_lt\nendaligned\n\nAs with losses option 2, this segment-wise approximation of a quadratic loss function also permits 'phantom losses' to avoid cycling thermal units when discrete unit commitment decisions are modeled. In this case, the additional constraints below are also added to ensure that auxiliary segments variables do not exceed maximum value per segment and that they are filled in order; i.e., one segment cannot be non-zero unless prior segment is at its maximum value. Binary constraints deal with absolute value of power flow on each line. If the flow is positive, mathcalS^+_0lt must be zero; if flow is negative, mathcalS^+_0lt must be positive and takes on value of the full negative flow, forcing all mathcalS^+_mlt other segments (m geq 1) to be zero. Conversely, if the flow is negative, mathcalS^-_0lt must be zero; if flow is positive, mathcalS^-_0lt must be positive and takes on value of the full positive flow, forcing all mathcalS^-_mlt other segments (m geq 1) to be zero. Requiring segments to fill in sequential order and binary variables to ensure variables reflect the actual direction of power flows are both necessary to eliminate ``phantom losses'' from the solution. These constraints and binary decisions are ommited if the model is fully linear.\n\nbeginaligned\n\tmathcalS^+_mlt = overlinemathcalS_ml times ON^+_mlt quad forall m in 1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^-_mlt = overlinemathcalS_ml times ON^-_mlt quad forall m in1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^+_mlt geq ON^+_m+1lt times overlinemathcalS_ml quad forall m in 1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^-_mlt geq ON^-_m+1lt times overlinemathcalS_ml quad forall m in 1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^+_0lt leq varphi^max_l times (1- ON^+_1lt) quad forall l in mathcalL forall t in mathcalT\n\tmathcalS^-_0lt leq varphi^max_l times (1- ON^-_1lt) quad forall l in mathcalL forall t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Unit-Commitment","page":"Core","title":"Unit Commitment","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"ucommit.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.ucommit!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.ucommit!","text":"ucommit!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates decision variables and cost expressions associated with thermal plant unit commitment or start-up and shut-down decisions (cycling on/off)\n\nUnit commitment decision variables:\n\nThis function defines the following decision variables:\n\nnu_ytz\n\ndesignates the commitment state of generator cluster y in zone z at time t; chi_ytz represents number of startup decisions in cluster y in zone z at time t; zeta_ytz represents number of shutdown decisions in cluster y in zone z at time t.\n\nCost expressions:\n\nThe total cost of start-ups across all generators subject to unit commitment (y in UC) and all time periods, t is expressed as:\n\nbeginaligned\n\tC^start = sum_y in UC t in T omega_t times start_cost_yt times chi_yt\nendaligned\n\nThe sum of start-up costs is added to the objective function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#CO2","page":"Core","title":"CO2","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"co2.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.co2!-Tuple{JuMP.Model, Dict}","page":"Core","title":"GenX.co2!","text":"co2!(EP::Model, inputs::Dict)\n\nThis function creates expressions to account for CO2 emissions as well as captured and sequestrated CO2 from thermal generators. It also has the capability to model the negative CO2 emissions from bioenergy with carbon capture and storage. \n\n***** Expressions *****\n\nFor thermal generators which combust fuels (e.g., coal, natural gas, and biomass), the net CO2 emission to the environment is a function of fuel consumption, CO2 emission factor, CO2 capture fraction, and whether the feedstock is biomass. Biomass is a factor in this equation because biomass generators are assumed to generate zero net CO2 emissions, or negative net CO2 emissions in the case that the CO2 they emit is captured and sequestered underground.\n\nIf a user wishes to represent a generator that combusts biomass, then in the resource .csv files, the \"Biomass\" column (boolean, 1 or 0), which represents if a generator y uses biomass or not, should be set to 1. The CO2 emissions from such a generator will be assumed to be zero without CCS and negative with CCS.\n\nThe CO2 emissions from generator y at time t are determined by total fuel consumption (MMBTU) multiplied by the CO2 content of the fuel (tCO2/MMBTU), and by (1 - Biomass [0 or 1] - CO2 capture fraction [a fraction, between 0 - 1]). The CO2 capture fraction could be differernt during the steady-state and startup events (generally startup events have a lower CO2 capture fraction), so we use distinct CO2 capture fractions to determine the emissions. In short, the CO2 emissions for a generator depend on the CO2 emission factor from fuel combustion, the CO2 capture fraction, and whether the generator uses biomass.\n\nbeginaligned\neEmissionsByPlant_gt = (1-Biomass_y- CO2_Capture_Fraction_y) * vFuel_yt * CO2_content + (1-Biomass_y- CO2_Capture_Fraction_Startup_y) * eStartFuel_yt * CO2_content \nhspace1cm forall y in G forall t in T Biomass_y in 01\nendaligned\n\nWhere Biomass_y represents a binary variable (1 or 0) that determines if the generator y uses biomass, and CO2_Capture_Fraction_y represents a fraction for CO2 capture rate.\n\nIn addition to CO2 emissions, for generators with a non-zero CO2 capture rate, we also determine the amount of CO2 being captured and sequestered. The CO2 emissions from generator y at time t, denoted by eEmissionsCaptureByPlant_gt, are determined by total fuel consumption (MMBTU) multiplied by the CO_2 content of the fuel (tCO2/MMBTU), times CO2 capture rate. \n\nbeginaligned\neEmissionsCaptureByPlant_gt = CO2_Capture_Fraction_y * vFuel_yt * CO2_content + CO2_Capture_Fraction_Startup_y * eStartFuel_yt * CO2_content\nhspace1cm forall y in G forall t in T\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.write_co2-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Core","title":"GenX.write_co2","text":"write_co2(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting time-dependent CO2 emissions by zone.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Fuel","page":"Core","title":"Fuel","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"fuel.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.fuel!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.fuel!","text":"fuel!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates expressions to account for total fuel consumption (e.g., coal, natural gas, hydrogen, etc). It also has the capability to model heat rates that are a function of load via a piecewise-linear approximation.\n\n***** Expressions ****** Users have two options to model the fuel consumption as a function of power generation: (1). Use a constant heat rate, regardless of the minimum load or maximum load; and (2). Use the PiecewiseFuelUsage-related parameters to model the fuel consumption via a piecewise-linear approximation of the heat rate curves. By using this option, users can represent the fact that most generators have a decreasing heat rate as a function of load.\n\n(1). Constant heat rate. The fuel consumption for power generation vFuel_yt is determined by power generation (vP_yt) mutiplied by the corresponding heat rate (Heat_Rate_y). The fuel costs for power generation and start fuel for a plant y at time t, denoted by eCFuelOut_yt and eFuelStart, are determined by fuel consumption (vFuel_yt and eStartFuel) multiplied by the fuel costs ($/MMBTU) (2). Piecewise-linear approximation With this formulation, the heat rate of generators becomes a function of load. In reality this relationship takes a nonlinear form, but we model it through a piecewise-linear approximation:\n\nbeginaligned\nvFuel_yt = vP_yt * h_yx + U_gt* f_yx\nhspace1cm forall y in G forall t in T forall x in X\nendaligned\n\nWhere h_yx represents the heat rate slope for generator y in segment x [MMBTU/MWh], f_yx represents the heat rate intercept (MMBTU) for a generator y in segment x [MMBTU], and U_yt represents the commitment status of a generator y at time t. These parameters are optional inputs to the resource .csv files. When Unit commitment is on, if a user provides slope and intercept, the standard heat rate (i.e., HeatRateMMBTUperMWh) will not be used. When unit commitment is off, the model will always use the standard heat rate. The user should determine the slope and intercept parameters based on the CapSize of the plant. For example, when a plant is operating at the full load (i.e., power output equal to the CapSize), the fuel usage determined by the effective segment divided by Cap_Size should be equal to the heat rate at full-load.\n\nSince fuel consumption and fuel costs are postive, the optimization will force the fuel usage to be equal to the highest fuel usage segment for any given value of vP. When the power output is zero, the commitment variable U_gt will bring the intercept to be zero such that the fuel consumption is zero when thermal units are offline.\n\nIn order to run piecewise fuel consumption module, the unit commitment must be turned on (UC = 1 or 2), and users should provide PWFUSlope* and PWFUIntercept* for at least one segment. \n\nTo enable resources to use multiple fuels during both startup and normal operational processes, three additional variables were added: fuel i consumption by plant y at time t (vMulFuel_yit); startup fuel consumption for single-fuel plants (vStartFuel_yt); and startup fuel consumption for multi-fuel plants (vMulStartFuel_yit). By making startup fuel consumption variables, the model can choose the startup fuel to meet the constraints. \n\nFor plants using multiple fuels:\n\nDuring startup, heat input from multiple startup fuels are equal to startup fuel requirements in plant y at time t: StartFuelMMBTUperMW times Capsize.\n\nbeginaligned\nsum_i in mathcalI vMulStartFuels_y i t= CapSize_y times StartFuelMMBTUperMW_y times vSTART_yt\nendaligned\n\nDuring normal operation, the sum of fuel consumptions from multiple fuels dividing by the correspnding heat rates, respectively, is equal to vPower in plant y at time t. \n\nbeginaligned\nsum_i in mathcalI fracvMulFuels_y i t HeatRate_iy = vPower_yt\nendaligned\n\nThere are also constraints on how much heat input each fuel can provide, which are specified by MinCofire and MaxCofire. ```math \\begin{aligned} vMulFuels{y, i, t} >= vPower{y,t} \\times MinCofire{i} \\end{aligned} \\begin{aligned} vMulFuels{y, i, t} <= vPower{y,t} \\times MaxCofire{i} \\end{aligned}\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#How-to-contribute-to-GenX","page":"Developer Docs","title":"How to contribute to GenX","text":"","category":"section"},{"location":"developer_guide/#Introduction","page":"Developer Docs","title":"Introduction","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX is an open-source project, and we welcome contributions from the community. This guide aims to help you get started with GenX and explain how to contribute to the project. In general, the two main ways to contribute to GenX are:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Use of GitHub issues to report bugs and request new features\nUse of GitHub pull requests (PR) to submit code changes","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"tip: Tip\nWe encourage every contributors to read this guide, which contains some guidelines on how to contribute to a collaborative project like GenX.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The following sections describe in more detail how to work with GenX resources and how to add a new resource to GenX.","category":"page"},{"location":"developer_guide/#GenX-resources","page":"Developer Docs","title":"GenX resources","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"In GenX, a resource is defined as an instance of a GenX resource type, a subtype of an AbstractResource. This allows the code to use multiple dispatch and define a common interface (behavior) for all resources in the code. Type hierarchy of GenX resources:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"(Image: Type hierarchy of GenX resources)","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"note: Note\nAll the interface and utility functions available for resources are defined in the resources.jl file. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The set of all the resource types available in GenX are contained in the resource_types Tuple defined at the of the resources.jl file. During the initialization process, GenX reads the input data files and creates a new instance of the corresponding resource type for each row in the file. ","category":"page"},{"location":"developer_guide/#Resource-design-principles","page":"Developer Docs","title":"Resource design principles","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Resources in GenX are constructed from a set of input files (in .csv format, one for each type of resource) located in the resources folder inside the case folder. Each row in one of these files defines a new resource instance, and each column corresponds to an attribute of that resource type. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"warning: Warning\nThe first column of each input data file should be called Resource and contain a unique identifier for each resource.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, in the case below, the files Hydro.csv, Thermal.csv, Vre.csv, and Storage.csv contain the resource data for the hydro, thermal, VRE, and storage resources, respectively. These files are read by GenX during the initialization process and used to create the corresponding resource instances.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"case_folder\n ├── resources\n │ ├── Hydro.csv\n │ ├── Thermal.csv\n │ ├── Vre.csv\n │ └── Storage.csv\n ├── system\n │ └── Generators_variability.csv\n //\n ├── setting\n │ └── genx_settings.yml\n └── Run.jl","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"When loading the file Thermal.csv below, GenX will create three new resources of type Thermal and assign the values of the attributes of each resource from the columns in the input data file:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Thermal.csv\n\n resource │ zone │ existing_cap_mw │ inv_cost_per_mwyr │ heat_rate_mmbtu_per_mwh │\n String │ Int64 │ Float64 │ Float64 │ Float64 │\n────────────────────-┼───────┼─────────────────┼───────────────────┼─────────────────────────│\n NG_combined_cycle_1 │ 1 │ 100.0 │ 239841 │ 7.89 │\n NG_combined_cycle_2 │ 2 │ 200.0 │ 0.0 │ 8.29 │\n Biomass │ 3 │ 200.0 │ 81998 │ 9.9 │","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"These three resources, together with all the other resources in the data files, will be stored in the GenX inputs dictionary with the key RESOURCES.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> gen = inputs[\"RESOURCES\"]\njulia> length(gen) # returns the number of resources in the model\njulia> thermal(gen) # returns the indices of all thermal resources (Vector{Int64})\njulia> gen.Thermal # returns the thermal resources (Vector{Thermal})\njulia> gen.Thermal == gen[thermal(gen)] # returns true","category":"page"},{"location":"developer_guide/#Working-with-GenX-resources","page":"Developer Docs","title":"Working with GenX resources","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"To access the attributes of each resource, you can either use a function interface or the standard . notation. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, let's assume that thermal_gen is the vector of the three Thermal resources created from the input data file Thermal.csv shown above. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"note: Note\nIn the example below, we create the vector thermal_gen manually. However, in practice, this vector is automatically created by GenX when loading the input data file Thermal.csv.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"DocTestSetup = quote\n using GenX: AbstractResource, Thermal, resource_name, existing_cap_mw, inv_cost_per_mwyr, ids_with, ids_with_positive, ids_with_nonneg, ids_with_policy, resource_id, esr, haskey\nend","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> thermal_gen = [Thermal(Dict(:resource => \"NG_combined_cycle_1\", \n :existing_cap_mw => 100.0, \n :inv_cost_per_mwyr => 239841, \n :heat_rate_mmbtu_per_mwh => 7.89,\n :id => 23,\n :max_cap_mw => 100.0,\n :esr_1 => 1,)),\n Thermal(Dict(:resource => \"NG_combined_cycle_2\",\n :existing_cap_mw => 200.0,\n :inv_cost_per_mwyr => 0.0,\n :heat_rate_mmbtu_per_mwh => 8.29,\n :max_cap_mw => 0,\n :id => 24)),\n Thermal(Dict(:resource => \"Biomass\",\n :existing_cap_mw => 200.0,\n :inv_cost_per_mwyr => 81998,\n :heat_rate_mmbtu_per_mwh => 9.9, \n :max_cap_mw => 0,\n :lds => 1,\n :new_build => 1,\n :id => 25))];","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"To access the attributes of the resources in thermal_gen, you can either use the function interfaces defined in resources.jl (recommended), or you can use the standard . notation:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> resource_name(thermal_gen[1])\n\"NG_combined_cycle_1\"\njulia> resource_name.(thermal_gen)\n3-element Vector{String}:\n \"NG_combined_cycle_1\"\n \"NG_combined_cycle_2\"\n \"Biomass\"\njulia> existing_cap_mw(thermal_gen[1])\n100.0\njulia> existing_cap_mw.(thermal_gen)\n3-element Vector{Float64}:\n 100.0\n 200.0\n 200.0\njulia> thermal_gen[1].existing_cap_mw\n100.0","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Moreover, inside the resources.jl file, there is a set of utility functions to work with all the resources and that can be used as building blocks to create more complex functions:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Base.get: Returns the value of the attribute sym of the resource r. If the attribute is not defined for the resource, it returns the default value of that attribute.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> get(thermal_gen[1], :existing_cap_mw, 0)\n100.0\njulia> get(thermal_gen[1], :new_build, 0)\n0","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Base.haskey: Returns true if the resource r has the attribute sym, and false otherwise.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> haskey(thermal_gen[1], :existing_cap_mw)\ntrue\njulia> haskey(thermal_gen[1], :new_build)\nfalse","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Base.findall: Returns the indices of the resources in rs for which the function f returns true.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> findall(r -> isa(r,Thermal), thermal_gen) # returns the indices of the thermal resources in thermal_gen\n3-element Vector{Int64}:\n 23\n 24\n 25\njulia> findall(r -> get(r, :lds, 0) > 0, thermal_gen) # returns the indices of the resources in thermal_gen that have a Long Duration Storage (lds) attribute greater than 0\n1-element Vector{Int64}:\n 25\njulia> findall(r -> get(r, :new_build, 0) == 1, thermal_gen) # returns the indices of the resources in thermal_gen that are buildable (new_build = 1)\n1-element Vector{Int64}:\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with: Returns the indices of the resources in the vector rs for which the function f is different from default.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with(thermal_gen, inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"A similar function works with Symbols and Strings instead of getter functions:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with(thermal_gen, :inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with_policy: Returns the indices of the resources in the vector rs that have a policy with the name name and the tag tag.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with_policy(thermal_gen, esr, tag=1)\n1-element Vector{Int64}:\n 23","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with_positive: Returns the indices of the resources in the vector rs for which the getter function f returns a positive value.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with_positive(thermal_gen, inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23 \n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"A similar function works with Symbols and Strings instead of getter functions:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with_positive(thermal_gen, :inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with_nonneg: Returns the indices of the resources in rs for which the getter function f returns a non-negative value.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Other useful functions available in GenX are:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.resource_id: Returns the id of the resource r.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> resource_id(thermal_gen[1])\n23\njulia> resource_id.(thermal_gen)\n3-element Vector{Int64}:\n 23\n 24\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.resource_name: Returns the name of the resource r.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> resource_name(thermal_gen[1])\n\"NG_combined_cycle_1\"\njulia> resource_name.(thermal_gen)\n3-element Vector{String}:\n \"NG_combined_cycle_1\"\n \"NG_combined_cycle_2\"\n \"Biomass\"","category":"page"},{"location":"developer_guide/#How-to-add-a-new-resource-to-GenX","page":"Developer Docs","title":"How to add a new resource to GenX","text":"","category":"section"},{"location":"developer_guide/#Overview","page":"Developer Docs","title":"Overview","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX is designed to be modular and highly flexible to comply with the rapidly changing electricity landscape. For this reason, adding a new resource to GenX is relatively straightforward. This guide will walk you through the steps to do it.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"tip: Tip\nBefore you start, ensure you have read the section of the documentation about 1.4 Resources input files. This will help you understand the data format that GenX expects for each resource and where to place the input data files. ","category":"page"},{"location":"developer_guide/#Step-1:-Define-the-new-resource-data-type","page":"Developer Docs","title":"Step 1: Define the new resource data type","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The first step to add a new resource to GenX is to create a new GenX resource type. This is done by adding a new element to the resource_types list of symbols defined at the top of the resources.jl file. This list contains the names of all the resource types available in GenX. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, to add a new resource type called new_resource, you would need to add a new Symbol, :NewResource to the resource_types list:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"const resource_types = (:Thermal,\n :Vre,\n :Hydro,\n :Storage,\n :MustRun,\n :FlexDemand,\n :VreStorage,\n :Electrolyzer,\n :NewResource)","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"We encourage you to use CamelCase for the name of the new resource type.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The lines right after the resource_types list automatically create a new struct (composite type) for the new resource type. More importantly, the new resource type will be defined as a subtype of the GenX AbstractResource type. This is important because it allows the code to use multiple dispach and define a common interface (behavior) for all resources in GenX. For instance, the resource_id() function will return the id of any resource in GenX, regardless of its type (and therefore will automatically work for the newly created new_resource).","category":"page"},{"location":"developer_guide/#Step-2:-Add-the-filename-of-the-new-resource-type-to-GenX","page":"Developer Docs","title":"Step 2: Add the filename of the new resource type to GenX","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"In GenX, the attributes of a resource are automatically defined from the columns of the corresponding input data file (e.g., Thermal.csv file for the Thermal resources, Hydro.csv file for the Hydro resource, etc). The first column of these files should be called Resource and contain a unique identifier for each resource. The rest of the columns in the input data file will be used to define the attributes of the new resource type. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"So, the second step to add a new resource type to GenX is to add the filename of the input data file to GenX. The list of input data files that GenX loads during the initialization process are defined at the top of the load_resource_data.jl file, inside an internal function called _get_resource_info(). This function returns a NamedTuple called resource_info with the name of the input data file and the name of the resource type for each resource that is available in GenX. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"To add the new resource type to GenX, add a new item to resource_info, where the first field is the name of the input data file and the second is the name of the resource type that was created in Step 1. The names in resource_info are only used to make the code more readable and are arbitrary. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, if you are adding a new resource type called new_resource, you would need to add the following line to the resource_info: new_resource = (filename=\"New_resource.csv\", type=NewResource), as follows: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"function _get_resource_info()\n resource_info = (\n hydro = (filename=\"Hydro.csv\", type=Hydro),\n thermal = (filename=\"Thermal.csv\", type=Thermal),\n vre = (filename=\"Vre.csv\", type=Vre),\n storage = (filename=\"Storage.csv\", type=Storage),\n flex_demand = (filename=\"Flex_demand.csv\", type=FlexDemand),\n must_run = (filename=\"Must_run.csv\", type=MustRun),\n electrolyzer = (filename=\"Electrolyzer.csv\", type=Electrolyzer),\n vre_stor = (filename=\"Vre_stor.csv\", type=VreStorage)\n new_resource = (filename=\"New_resource.csv\", type=NewResource)\n )\n return resource_info\nend","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"With this simple edit, whenever the file New_resource.csv is found in the input data folder, GenX will automatically perform the following steps:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Load the new resource input file,\nCreate a new instance of the NewResource type for each row in the input data file,\nDefine the attributes of each NewResource from the columns in the input data file,\nPopulate the attributes of each NewResource with the values read from the input data file.\nAdd the new resources to the vector of resources in the model.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, if the input data file New_resource.csv contains the following data:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"New_resource.csv\n\n Resource │ Zone | Exisiting_capacity | attribute_1 | attribute_2\n String │ Int64 | Float64 | Float64 | Float64\n──────────┼───────┼────────────────────┼─────────────┼────────────\n new_res1 │ 1 │ 100.0 │ 6.2 │ 0.4\n new_res2 │ 1 │ 200.0 │ 0.1 │ 4.0\n new_res3 │ 2 │ 300.0 │ 2.0 │ 0.1","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX will create three new resources of type NewResource with the following attributes:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"resource: String with the name of the resource (e.g., new_res1, new_res2, new_res3)\nzone: Int64 with the zone of the resource (e.g., 1, 1, 2)\nexisting_capacity: Float64 with the existing capacity of the resource (e.g., 100.0, 200.0, 300.0)\nattribute_1: Float64 with the value of attribute_1 (e.g., 6.2, 0.1, 2.0)\nattribute_2: Float64 with the value of attribute_2 (e.g., 0.4, 4.0, 0.1)","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"See Step 3 for more details on how to work with the new resource type.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"warning: Warning\nEach resource type must contain a Resource attribute. This attribute should be String that uniquely identifies the resource. ","category":"page"},{"location":"developer_guide/#Step-3:-Work-with-the-new-resource-type","page":"Developer Docs","title":"Step 3: Work with the new resource type","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Once the new resource type has been defined and added to GenX, you can work with it as you would with any other resource type. To improve the robustness and readability of the code, we recommend that you define getter functions for the new attributes of the new resource type (e.g., a function zone(r) = r.zone to get the zone of the resource r). These functions can be defined in the resources.jl file. However, this is not strictly necessary, and you can access the attributes of the new resource type directly using the standard . notation:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"tip: Tip\nTo simplify the creation of getter functions for the new resource type, you can use the @interface macro available in GenX. This macro automatically creates a new function with the same name as the attribute and which returns the value of the attribute. For example, if you want to create a getter function for the attribute_1 of the NewResource type, these two ways are equivalent:julia> default_attribute_1 = 0.0 # default value for attribute_1\njulia> attribute_1(res::NewResource) = get(res, :attribute_1, default_attribute_1)\nattribute_1 (generic function with 1 method)\njulia> @interface(attribute_1, 0.0, NewResource)\nattribute_1 (generic function with 1 method)And then:julia> attribute_1(new_res1)\n6.2\njulia> new_res1.attribute_1\n6.2","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"DocTestSetup = nothing","category":"page"},{"location":"developer_guide/#Utility-functions-to-work-with-JuMP-expressions-in-GenX","page":"Developer Docs","title":"Utility functions to work with JuMP expressions in GenX","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Modules = [GenX]\nPages = [\"model/expression_manipulation.jl\"]","category":"page"},{"location":"developer_guide/#GenX.add_similar_to_expression!-Union{Tuple{dim2}, Tuple{dim1}, Tuple{V}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dim1}, AbstractArray{V, dim2}}} where {C, T, V, dim1, dim2}","page":"Developer Docs","title":"GenX.add_similar_to_expression!","text":"add_similar_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dim1}, expr2::AbstractArray{V, dim2}) where {C,T,V,dim1,dim2}\n\nAdd an array of some type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr). However, the accessed parts of both arrays must have the same dimensions.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.add_term_to_expression!-Union{Tuple{dims}, Tuple{V}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dims}, V}} where {C, T, V, dims}","page":"Developer Docs","title":"GenX.add_term_to_expression!","text":"add_term_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dims}, expr2::V) where {C,T,V,dims}\n\nAdd an entry of type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr).\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.check_addable_to_expr-Tuple{DataType, DataType}","page":"Developer Docs","title":"GenX.check_addable_to_expr","text":"check_addable_to_expr(C::DataType, T::DataType)\n\nCheck that two datatype can be added using addtoexpression!(). Raises an error if not.\n\nThis needs some work to make it more flexible. Right now it's challenging to use with GenericAffExpr{C,T} as the method only works on the constituent types making up the GenericAffExpr, not the resulting expression type. Also, the default MethodError from addtoexpression! is sometime more informative than the error message here.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.check_sizes_match-Union{Tuple{dim2}, Tuple{dim1}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{C, dim1}, AbstractArray{T, dim2}}} where {C, T, dim1, dim2}","page":"Developer Docs","title":"GenX.check_sizes_match","text":"check_sizes_match(expr1::AbstractArray{C, dim1}, expr2::AbstractArray{T, dim2}) where {C,T,dim1, dim2}\n\nCheck that two arrays have the same dimensions. If not, return an error message which includes the dimensions of both arrays.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.create_empty_expression!-Union{Tuple{N}, Tuple{JuMP.Model, Symbol, Tuple{Vararg{Int64, N}}}} where N","page":"Developer Docs","title":"GenX.create_empty_expression!","text":"create_empty_expression!(EP::Model, exprname::Symbol, dims::NTuple{N, Int64}) where N\n\nCreate an dense array filled with zeros which can be altered later. Other approaches to creating zero-filled arrays will often return an array of floats, not expressions. This can lead to errors later if a method can only operate on expressions.\n\nWe don't currently have a method to do this with non-contiguous indexing.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.fill_with_const!-Union{Tuple{dims}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dims}, Real}} where {C, T, dims}","page":"Developer Docs","title":"GenX.fill_with_const!","text":"fill_with_const!(arr::AbstractArray{GenericAffExpr{C,T}, dims}, con::Real) where {C,T,dims}\n\nFill an array of expressions with the specified constant, in-place.\n\nIn the future we could expand this to non AffExpr, using GenericAffExpr e.g. if we wanted to use Float32 instead of Float64\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.fill_with_zeros!-Union{Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dims}}, Tuple{dims}, Tuple{T}, Tuple{C}} where {C, T, dims}","page":"Developer Docs","title":"GenX.fill_with_zeros!","text":"fill_with_zeros!(arr::AbstractArray{GenericAffExpr{C,T}, dims}) where {C,T,dims}\n\nFill an array of expressions with zeros in-place.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.sum_expression-Union{Tuple{AbstractArray{C, dims}}, Tuple{dims}, Tuple{C}} where {C, dims}","page":"Developer Docs","title":"GenX.sum_expression","text":"sum_expression(expr::AbstractArray{C, dims}) where {C,dims} :: C\n\nSum an array of expressions into a single expression and return the result. We're using errors from addtoexpression!() to check that the types are compatible.\n\n\n\n\n\n","category":"method"}] +[{"location":"Tutorials/Tutorial_5_solve_model/#Tutorial-5:-Solving-the-Model","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In Tutorial 4, we went over how the model is generated when GenX is run using Run.jl. In the function run_genx_case_simple (or multistage), after generate_model is called, solve_model is called to solve the EP.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In this tutorial, we go over how to use JuMP to solve a model, what it looks like to solve GenX, and how to edit the solver settings.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#Table-of-Contents","page":"Tutorial 5: Solving the Model","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"A Simple Example\nGenX\nInfeasibility","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#A-Simple-Example","page":"Tutorial 5: Solving the Model","title":"A Simple Example","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"From Tutorial 4, we have the model:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"beginaligned\n min 10 x + 15 y textObjective function (cost) \n textst \n x + y geq 10 textGrid Demand\n 55x + 70y leq 1000 textConstruction constraint\n 40 x + 5 y leq 200 textEmissions constraint \n x y geq 0 textNon-negativity constraints\nendaligned","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"using JuMP\nusing HiGHS","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"power = Model(HiGHS.Optimizer)\n\n@variable(power,x,Int) # Coal\n@variable(power,y,Int) # Wind\n\n@constraint(power, non_neg_x, x >= 0) # Non-negativity constraint (can't have negative power plants!)\n@constraint(power, non_neg_y, y >= 0) # Non-negativity constraint\n\n@constraint(power, emissions, 40x + 5y <= 200) # Emisisons constraint\n@constraint(power, construction_costs, 55x + 70y <= 1000) # Cost of constructing a new plant\n\n@constraint(power, demand, x + y >= 10) # Grid demand\n\n@expression(power,objective,10x+15y)\n\n@objective(power, Min, objective)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"10 x + 15 y ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"JuMP uses the function optimize!(model) to solve the LP:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"optimize!(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 3 rows, 2 cols, 6 nonzeros\n 3 rows, 2 cols, 6 nonzeros\n Objective function is integral with scale 0.2\n \n Solving MIP model with:\n 3 rows\n 2 cols (0 binary, 2 integer, 0 implied int., 0 continuous)\n 6 nonzeros\n \n Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work \n Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time\n \n 0 0 0 0.00% 90 inf inf 0 0 0 0 0.0s\n \n Solving report\n Status Optimal\n Primal bound 130\n Dual bound 130\n Gap 0% (tolerance: 0.01%)\n Solution status feasible\n 130 (objective)\n 0 (bound viol.)\n 0 (int. viol.)\n 0 (row viol.)\n Timing 0.00 (total)\n 0.00 (presolve)\n 0.00 (postsolve)\n Nodes 1\n LP iterations 1 (total)\n 0 (strong br.)\n 0 (separation)\n 0 (heuristics)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"We can use the function value.() to get the value of each variable, and objective_value() to get the total objective value.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"println(\"# Coal Plants: \", value.(x))\nprintln(\"# Wind Farms: \", value.(y))\nprintln(\"Cost: \", objective_value(power))","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" # Coal Plants: 4.0\n # Wind Farms: 6.0\n Cost: 130.0","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"We can also use the JuMP function solution_summary to see more details of the solution:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"solution_summary(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" * Solver : HiGHS\n \n * Status\n Result count : 1\n Termination status : OPTIMAL\n Message from the solver:\n \"kHighsModelStatusOptimal\"\n \n * Candidate solution (result #1)\n Primal status : FEASIBLE_POINT\n Dual status : NO_SOLUTION\n Objective value : 1.30000e+02\n Objective bound : 1.30000e+02\n Relative gap : 0.00000e+00\n \n * Work counters\n Solve time (sec) : 3.36621e-03\n Simplex iterations : 1\n Barrier iterations : -1\n Node count : 1","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#GenX","page":"Tutorial 5: Solving the Model","title":"GenX","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"Let's optimize the GenX model created in the last Tutorial. To do so, we'll create the inputs for generate_model and run it. ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"using GenX","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"case = joinpath(\"example_systems/1_three_zones\") \n\ngenx_settings = GenX.get_settings_path(case, \"genx_settings.yml\");\nwriteoutput_settings = GenX.get_settings_path(case, \"output_settings.yml\")\nsetup = GenX.configure_settings(genx_settings,writeoutput_settings)\n\nsettings_path = GenX.get_settings_path(case)\n\n### Create TDR_Results\nTDRpath = joinpath(case, setup[\"TimeDomainReductionFolder\"])\nsystem_path = joinpath(case, setup[\"SystemFolder\"])\n\nif setup[\"TimeDomainReduction\"] == 1\n GenX.prevent_doubled_timedomainreduction(system_path)\n if !GenX.time_domain_reduced_files_exist(TDRpath)\n println(\"Clustering Time Series Data (Grouped)...\")\n GenX.cluster_inputs(case, settings_path, setup)\n else\n println(\"Time Series Data Already Clustered.\")\n end\nend\n\nOPTIMIZER = GenX.configure_solver(settings_path,HiGHS.Optimizer);\n\ninputs = GenX.load_inputs(setup, case)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"EP = GenX.generate_model(setup,inputs,OPTIMIZER)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 18492\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 5544 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 7398 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 27730 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 2 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 18490 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cCapacityResMargin, cESRShare, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cZoneMaxCapReq, cZoneMinCapReq, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eCapResMarBalance, eCapResMarBalanceStor, eCapResMarBalanceThermal, eCapResMarBalanceVRE, eELOSS, eELOSSByZone, eESR, eESRDischarge, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eMaxCapRes, eMaxCapResInvest, eMinCapRes, eMinCapResInvest, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vZERO","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"The function solve_model(model, setup) uses optimize to optimize the model:","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"solution = optimize!(EP) # GenX.solve_model(EP,setup)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"objective_value(EP)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" 9776.57688838726","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/#Infeasibility","page":"Tutorial 5: Solving the Model","title":"Infeasibility","text":"","category":"section"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In some cases, your model may not be able to return a value. This happens when no value can be found that satisfies all constraints. To see this, let's go back to our simple example and change one of the parameters to break the model.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"beginaligned\n min 10 x + 15 y textObjective function (cost) \n textst \n x + y geq 10 textGrid Demand\n 55x + 70y leq 1000 textConstruction constraint\n 40 x + 5 y leq 200 textEmissions constraint \n 7 x + 30 y geq 500 textbfNew Constraint \n x y geq 0 textNon-negativity constraints\nendaligned","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"@constraint(power, new, 7x + 30y >= 500)\n","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"7 x + 30 y geq 500 ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"print(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"beginaligned\nminquad 10 x + 15 y\ntextSubject to quad x geq 0\n y geq 0\n x + y geq 10\n 7 x + 30 y geq 500\n 40 x + 5 y leq 200\n 55 x + 70 y leq 1000\n x in mathbbZ\n y in mathbbZ\nendaligned ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"optimize!(power)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":" Presolving model\n Presolve: Infeasible\n \n Solving report\n Status Infeasible\n Primal bound inf\n Dual bound -inf\n Gap inf\n Solution status -\n Timing 0.00 (total)\n 0.00 (presolve)\n 0.00 (postsolve)\n Nodes 0\n LP iterations 0 (total)\n 0 (strong br.)\n 0 (separation)\n 0 (heuristics)","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"In this case, the infeasibility was detected on the presovle since it's clear no solution would fit within all constraints. For information on how to debug an infeasible solution, see the JuMP documentaion. Some solvers, such as Gurobi, will compute what is causing the conflict, e.g. which constraints are infeasible with one another (HiGHS does not do this). ","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"GenX version 0.4 has the feature ComputeConflict in settings. If the model does not work, try setting ComputeConflict = 1, and the conflicting constraints will be returned.","category":"page"},{"location":"Tutorials/Tutorial_5_solve_model/","page":"Tutorial 5: Solving the Model","title":"Tutorial 5: Solving the Model","text":"Tutorial 6 describes the solver settings, how to change them, and the effects of PreSolve, Crossover, and Feasibility Tolerance.","category":"page"},{"location":"Model_Reference/Resources/thermal_no_commit/#Thermal-No-Commit","page":"Thermal No Commit","title":"Thermal No Commit","text":"","category":"section"},{"location":"Model_Reference/Resources/thermal_no_commit/","page":"Thermal No Commit","title":"Thermal No Commit","text":"Modules = [GenX]\nPages = [\"thermal_no_commit.jl\"]","category":"page"},{"location":"Model_Reference/Resources/thermal_no_commit/#GenX.thermal_no_commit!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal No Commit","title":"GenX.thermal_no_commit!","text":"thermal_no_commit!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the operating constraints for thermal power plants NOT subject to unit commitment constraints on power plant start-ups and shut-down decisions (y in H setminus UC).\n\nRamping limits\n\nThermal resources not subject to unit commitment (y in H setminus UC) adhere instead to the following ramping limits on hourly changes in power output:\n\nbeginaligned\n\tTheta_yzt-1 - Theta_yzt leq kappa_yz^down Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt - Theta_yzt-1 leq kappa_yz^up Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 1-2 in the code)\n\nThis set of time-coupling constraints wrap around to ensure the power output in the first time step of each year (or each representative period), t in mathcalT^start, is within the eligible ramp of the power output in the final time step of the year (or each representative period), t+tau^period-1.\n\nMinimum and maximum power output\n\nWhen not modeling regulation and reserves, thermal units not subject to unit commitment decisions are bound by the following limits on maximum and minimum power output:\n\nbeginaligned\n\tTheta_yzt geq rho^min_yz times Delta^total_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt leq rho^max_yzt times Delta^total_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 3-4 in the code)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_no_commit/#GenX.thermal_no_commit_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Thermal No Commit","title":"GenX.thermal_no_commit_operational_reserves!","text":"thermal_no_commit_operational_reserves!(EP::Model, inputs::Dict)\n\nThis function is called by the thermal_no_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants not subject to unit commitment constraints on power plant start-ups and shut-down decisions.\n\nMaximum contributions to frequency regulation and reserves\n\nThermal units not subject to unit commitment adhere instead to the following constraints on maximum reserve and regulation contributions:\n\nbeginaligned\n\tf_yzt leq upsilon^reg_yz times rho^max_yzt Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tr_yzt leq upsilon^rsv_yz times rho^max_yzt Delta^texttotal_yz hspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nwhere f_yzt is the frequency regulation contribution limited by the maximum regulation contribution upsilon^reg_yz, and r_yzt is the reserves contribution limited by the maximum reserves contribution upsilon^rsv_yz. Limits on reserve contributions reflect the maximum ramp rate for the thermal resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nMinimum and maximum power output\n\nWhen modeling regulation and spinning reserves, thermal units not subject to unit commitment are bound by the following limits on maximum and minimum power output:\n\nbeginaligned\n\tTheta_yzt - f_yzt geq rho^min_yz times Delta^texttotal_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt + f_yzt + r_yzt leq rho^max_yzt times Delta^texttotal_yz\n\thspace1cm forall y in mathcalH setminus UC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nNote there are multiple versions of these constraints in the code in order to avoid creation of unecessary constraints and decision variables for thermal units unable to provide regulation and/or reserves contributions due to input parameters (e.g. Reg_Max=0 and/or RSV_Max=0).\n\n\n\n\n\n","category":"method"},{"location":"Model_Concept_Overview/model_notation/#Model-Notation","page":"Notation","title":"Model Notation","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/#Model-Indices-and-Sets","page":"Notation","title":"Model Indices and Sets","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"Notation Description\nt in mathcalT where t denotes an time step and mathcalT is the set of time steps over which grid operations are modeled\nmathcalT^interior subseteq mathcalT^ where mathcalT^interior is the set of interior timesteps in the data series\nmathcalT^start subseteq mathcalT where mathcalT^start is the set of initial timesteps in the data series. mathcalT^start=1 when representing entire year as a single contiguous period; mathcalT^start=left(m-1right) times tau^period+1 m in mathcalM, which corresponds to the first time step of each representative period m in mathcalM\nn in mathcalN where n corresponds to a contiguous time period and mathcalN corresponds to the set of contiguous periods of length tau^period that make up the input time series (e.g. demand, variable renewable energy availability) to the model\nmathcalN^rep subseteq mathcalN where mathcalN^rep corresponds to the set of representative time periods that are selected from the set of contiguous periods, mathcalM\nm in mathcalM where m corresponds to a representative time period and mathcalM corresponds to the set of representative time periods indexed as per their chronological ocurrence in the set of contiguous periods spanning the input time series data, i.e. mathcalN\nz in mathcalZ where z denotes a zone and mathcalZ is the set of zones in the network\nl in mathcalL where l denotes a line and mathcalL is the set of transmission lines in the network\ny in mathcalG where y denotes a technology and mathcalG is the set of available technologies\nmathcalH subseteq mathcalG where mathcalH is the subset of thermal resources\nmathcalVRE subseteq mathcalG where mathcalVRE is the subset of curtailable Variable Renewable Energy (VRE) resources\noverlinemathcalVRE^yz set of VRE resource bins for VRE technology type y in mathcalVRE in zone z\nmathcalCE subseteq mathcalG where mathcalCE is the subset of resources qualifying for the clean energy standard policy constraint\nmathcalUC subseteq mathcalH where mathcalUC is the subset of thermal resources subject to unit commitment constraints\ns in mathcalS where s denotes a segment and mathcalS is the set of consumers segments for price-responsive demand curtailment\nmathcalO subseteq mathcalG where mathcalO is the subset of storage resources excluding heat storage and hydro storage\no in mathcalO where o denotes a storage technology in a set mathcalO\nmathcalO^sym subseteq mathcalO where mathcalO^sym corresponds to the set of energy storage technologies with equal (or symmetric) charge and discharge power capacities\nmathcalO^asym subseteq mathcalO where mathcalO^asym corresponds to the set of energy storage technologies with independently sized (or asymmetric) charge and discharge power capacities\nmathcalO^LDES subseteq mathcalO where mathcalO^LDES corresponds to the set of long-duration energy storage technologies for which inter-period energy exchange is permitted when using representative periods to model annual grid operations\nmathcalVS subseteq mathcalG where mathcalVS is the subset of co-located VRE and storage resources\nmathcalVS^pv subseteq mathcalVS where mathcalVS^pv corresponds to the set of co-located VRE and storage resources with a solar PV component\nmathcalVS^wind subseteq mathcalVS where mathcalVS^wind corresponds to the set of co-located VRE and storage resources with a wind component\nmathcalVS^inv subseteq mathcalVS where mathcalVS^inv corresponds to the set of co-located VRE and storage resources with an inverter component\nmathcalVS^stor subseteq mathcalVS where mathcalVS^stor corresponds to the set of co-located VRE and storage resources with a storage component\nmathcalVS^sym dc subseteq mathcalVS where mathcalVS^sym dc corresponds to the set of co-located VRE and storage resources with a storage DC component with equal (or symmetric) charge and discharge power capacities\nmathcalVS^sym ac subseteq mathcalVS where mathcalVS^sym ac corresponds to the set of co-located VRE and storage resources with a storage AC component with equal (or symmetric) charge and discharge power capacities\nmathcalVS^asym dc dis subseteq mathcalVS where mathcalVS^asym dc dis corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) discharge power capabilities\nmathcalVS^asym dc cha subseteq mathcalVS where mathcalVS^asym dc cha corresponds to the set of co-located VRE and storage resources with a storage DC component with independently sized (or asymmetric) charge power capabilities\nmathcalVS^asym ac dis subseteq mathcalVS where mathcalVS^asym ac dis corresponds to the set of co-located VRE and storage with a storage AC component with independently sized (or asymmetric) discharge power capabilities\nmathcalVS^asym ac cha subseteq mathcalVS where mathcalVS^asym ac cha corresponds to the set of co-located VRE and storage resources with a storage AC component with independently sized (or asymmetric) charge power capabilities\nmathcalVS^LDES subseteq mathcalVS where mathcalVS^LDES corresponds to the set of co-located VRE and storage resources with a long-duration energy storage component for which inter-period energy exchange is permitted when using representative periods to model annual grid operations\nmathcalW subseteq mathcalG where mathcalW set of hydroelectric generators with water storage reservoirs\nmathcalW^nocap subseteq mathcalW where mathcalW^nocap is a subset of set of $ \\mathcal{W}$ and represents resources with unknown reservoir capacity\nmathcalW^cap subseteq mathcalW where mathcalW^cap is a subset of set of $ \\mathcal{W}$ and represents resources with known reservoir capacity\nmathcalMR subseteq mathcalG where mathcalMR set of must-run resources\nmathcalDF subseteq mathcalG where mathcalDF set of flexible demand resources\nmathcalELECTROLYZER subseteq mathcalG where mathcalELECTROLYZER set of electrolyzer resources (optional set)\nmathcalG_p^ESR subseteq mathcalG where mathcalG_p^ESR is a subset of mathcalG that is eligible for Energy Share Requirement (ESR) policy constraint p\np in mathcalP where p denotes a instance in the policy set mathcalP\nmathcalP^ESR subseteq mathcalP Energy Share Requirement type policies\nmathcalP^CO_2 subseteq mathcalP CO_2 emission cap policies\nmathcalP^CO_2_mass subseteq mathcalP^CO_2 CO_2 emissions limit policy constraints, mass-based\nmathcalP^CO_2_demand subseteq mathcalP^CO_2 CO_2 emissions limit policy constraints, demand and emission-rate based\nmathcalP^CO_2_gen subseteq mathcalP^CO_2 CO_2 emissions limit policy constraints, generation emission-rate based\nmathcalP^CRM subseteq mathcalP Capacity reserve margin (CRM) type policy constraints\nmathcalP^MinTech subseteq mathcalP Minimum Capacity Carve-out type policy constraint\nmathcalZ^ESR_p subseteq mathcalZ set of zones eligible for ESR policy constraint p in mathcalP^ESR\nmathcalZ^CRM_p subseteq mathcalZ set of zones that form the locational deliverable area for capacity reserve margin policy constraint p in mathcalP^CRM\nmathcalZ^CO_2_pmass subseteq mathcalZ set of zones are under the emission cap mass-based cap-and-trade policy constraint p in mathcalP^CO_2_mass\nmathcalZ^CO_2_pdemand subseteq mathcalZ set of zones are under the emission cap demand-and-emission-rate based cap-and-trade policy constraint p in mathcalP^CO_2_demand\nmathcalZ^CO_2_pgen subseteq mathcalZ set of zones are under the emission cap generation emission-rate based cap-and-trade policy constraint p in mathcalP^CO2gen\nmathcalL_p^in subseteq mathcalL The subset of transmission lines entering Locational Deliverability Area of capacity reserve margin policy p in mathcalP^CRM\nmathcalL_p^out subseteq mathcalL The subset of transmission lines leaving Locational Deliverability Area of capacity reserve margin policy p in mathcalP^CRM\nmathcalQualified subseteq mathcalG where mathcalQualified is the subset of generation and storage resources eligible to supply electrolyzers within the same zone (optional set)","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/#Decision-Variables","page":"Notation","title":"Decision Variables","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"Notation Description\nOmega_yz in mathbbR_+ Installed capacity in terms of the number of units (each unit, being of size overlineOmega_yz^size) of resource y in zone z [Dimensionless] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the grid connection in [MW AC])\nOmega^energy_yz in mathbbR_+ Installed energy capacity of resource y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the installed capacity of the storage component in MWh)\nOmega^charge_yz in mathbbR_+ Installed charging power capacity of resource y in zone z - only applicable for storage resources, y in mathcalO^asym [MW]\nOmega^pv_yz in mathbbR_+ Installed solar PV capacity of resource y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nOmega^wind_yz in mathbbR_+ Installed wind capacity of resource y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nOmega^inv_yz in mathbbR_+ Installed inverter capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nOmega^dcdis_yz in mathbbR_+ Installed storage DC discharge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nOmega^dccha_yz in mathbbR_+ Installed storage DC charge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nOmega^acdis_yz in mathbbR_+ Installed storage AC discharge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nOmega^accha_yz in mathbbR_+ Installed storage AC charge capacity of resource y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nDelta_yz in mathbbR_+ Retired capacity of technology y from existing capacity in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the grid connection in MW AC)\nDelta^energy_yz in mathbbR_+ Retired energy capacity of technology y from existing capacity in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the retired capacity of the storage component in MWh)\nDelta^charge_yz in mathbbR_+ Retired charging capacity of technology y from existing capacity in zone z - only applicable for storage resources, y in mathcalO^asym[MW]\nDelta^pv_yz in mathbbR_+ Retired solar PV capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nDelta^wind_yz in mathbbR_+ Retired wind capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nDelta^inv_yz in mathbbR_+ Retired inverter capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nDelta^dcdis_yz in mathbbR_+ Retired storage DC discharge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nDelta^dccha_yz in mathbbR_+ Retired storage DC charge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nDelta^acdis_yz in mathbbR_+ Retired storage AC discharge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nDelta^accha_yz in mathbbR_+ Retired storage AC charge capacity of technology y from existing capacity in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nDelta_yz^total in mathbbR_+ Total installed capacity of technology y in zone z [MW] (Note that co-located VRE and storage resources, this value represents the total capacity of the grid connection in MW AC)\nDelta_yz^totalenergy in mathbbR_+ Total installed energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that co-located VRE and storage resources, this value represents the total installed energy capacity of the storage component in MWh)\nDelta_yz^totalcharge in mathbbR_+ Total installed charging power capacity of technology y in zone z - only applicable for storage resources, y in mathcalO^asym [MW]\nDelta_yz^totalpv in mathbbR_+ Total installed solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nDelta_yz^totalwind in mathbbR_+ Total installed wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nDelta_yz^totalinv in mathbbR_+ Total installed inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nDelta_yz^totaldcdis in mathbbR_+ Total installed storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nDelta_yz^totaldccha in mathbbR_+ Total installed storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nDelta_yz^totalacdis in mathbbR_+ Total installed storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nDelta_yz^totalaccha in mathbbR_+ Total installed storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nbigtriangleupvarphi^max_l Additional transmission capacity added to line l [MW]\nTheta_yzt in mathbbR_+ Energy injected into the grid by technology y at time step t in zone z [MWh]\nTheta^pv_yzt in mathbbR_+ Energy generated by the solar PV component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MWh]\nTheta^wind_yzt in mathbbR_+ Energy generated by the wind component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MWh]\nTheta^dc_yzt in mathbbR_+ Energy discharged by the storage DC component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a discharge DC component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis [MWh]\nTheta^ac_yzt in mathbbR_+ Energy discharged by the storage AC component into the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a discharge AC component, y in mathcalVS^symac cup y in mathcalVS^asymacdis [MWh]\nPi_yzt in mathbbR_+ Energy withdrawn from grid by technology y at time step t in zone z [MWh]\nPi^dc_yzt in mathbbR_+ Energy withdrawn from the VRE and grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a charge DC component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha [MWh]\nPi^ac_yzt in mathbbR_+ Energy withdrawn from the VRE and grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with a charge AC component, y in mathcalVS^symac cup y in mathcalVS^asymaccha [MWh]\nGamma_yzt in mathbbR_+ Stored energy level of technology y at end of time step t in zone z [MWh]\nLambda_szt in mathbbR_+ Non-served energy/curtailed demand from the price-responsive demand segment s in zone z at time step t [MWh]\nl_lt in mathbbR_+ Losses in line l at time step t [MWh]\nvarrho_yztin mathbbR_+ Spillage from a reservoir technology y at end of time step t in zone z [MWh]\nf_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves from technology y in zone z at time t\\footnote{Regulation reserve contribution are modeled to be symmetric, consistent with current practice in electricity markets}\nr_yzt in mathbbR_+ Upward spinning reserves contribution [MW] from technology y in zone z at time t (we are not modeling down spinning reserves since these are usually never binding for high variable renewable energy systems)\nf^charge_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves from charging storage technology y in zone z at time t\nf^discharge_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves from discharging storage technology y in zone z at time t\nr^charge_yzt in mathbbR_+ Upward spinning reserves contribution [MW] from charging storage technology y in zone z at time t\nr^discharge_yzt in mathbbR_+ Upward spinning reserves contribution [MW] from discharging storage technology y in zone z at time t\nr^unmet_t in mathbbR_+ Shortfall in provision of upward operating spinning reserves during each time period t in T\nf^pv_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the solar PV component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv\nr^pv_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the solar PV component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv\nf^wind_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the wind component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind\nr^wind_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the wind component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind\nf^dcdis_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage DC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis\nr^dcdis_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage DC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis\nf^dccha_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage DC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha\nr^dccha_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage DC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha\nf^acdis_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage AC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^symac cup y in mathcalVS^asymacdis\nr^acdis_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage AC discharge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^symac cup y in mathcalVS^asymacdis\nf^accha_yztin mathbbR_+ Frequency regulation contribution [MW] for up and down reserves for the storage AC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^symac cup y in mathcalVS^asymaccha\nr^accha_yzt in mathbbR_+ Upward spinning reserves contribution [MW] for the storage AC charge component from technology y in zone z at time t - only applicable for co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^symac cup y in mathcalVS^asymaccha\nalpha^ContingencyAux_yz in 01 Binary variable that is set to be 1 if the total installed capacity Delta^texttotal_yz 0 for any generator y in mathcalUC and zone z, and can be 0 otherwise\nPhi_lt in mathbbR_+ Power flow in line l at time step t [MWh]\ntheta_zt in mathbbR Volta phase angle in zone z at time step t [radian]\nv_yzt Commitment state of the generation cluster y in zone z at time t\nmathcalX_yzt Number of startup decisions, of the generation cluster y in zone z at time t\nzeta_yzt Number of shutdown decisions, of the generation cluster y in zone z at time t\nmathcalQ_on in mathbbR_+ Inventory of storage of type o at the beginning of input period n [MWh]\nDeltamathcalQ_om in mathbbR Excess storage inventory built up during representative period m [MWh]\nON^+_lt in 01 Binary variable to activate positive flows on line l in time t\nTransON^+_lt in mathbbR_+ Variable defining maximum positive flow in line l in time t [MW]\nTheta^CRM_yzt in mathbbR_+ \"Virtual\" energy discharged by a storage resource that contributes to the capacity reserve margin for technology y at time step t in zone z - only applicable for storage resources with activated capacity reserve margin policies, y in mathcalO [MWh]\nPi^CRM_yzt in mathbbR_+ \"Virtual\" energy withdrawn by a storage resource from the grid by technology y at time step t in zone z - only applicable for storage resources with activated capacity reserve margin policies, y in mathcalO [MWh]\nTheta^CRMdc_yzt in mathbbR_+ \"Virtual\" energy discharged by a storage DC component that contributes to the capacity reserve margin for technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nPi^CRMdc_yzt in mathbbR_+ \"Virtual\" energy withdrawn by a storage DC component from the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nTheta^CRMac_yzt in mathbbR_+ \"Virtual\" energy discharged by a storage AC component that contributes to the capacity reserve margin for technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nPi^CRMac_yzt in mathbbR_+ \"Virtual\" energy withdrawn by a storage AC component from the grid by technology y at time step t in zone z - only applicable for co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalVS^stor [MWh]\nGamma^CRM_yzt in mathbbR_+ Total \"virtual\" state of charge being held in reserves for technology y at time step t in zone z - only applicable for standalone storage and co-located VRE and storage resources with activated capacity reserve margin policies, y in mathcalO cup y in mathcalVS^stor [MWh]","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/#Parameters","page":"Notation","title":"Parameters","text":"","category":"section"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"Notation Description\nD_zt Electricity demand in zone z and at time step t [MWh]\ntau^period number of time steps in each representative period w in mathcalW^rep and each input period w in mathcalW^input\nomega_t weight of each model time step omega_t =1 forall t in T when modeling each time step of the year at an hourly resolution [1/year]\nn_s^slope Cost of non-served energy/demand curtailment for price-responsive demand segment s [$/MWh]\nn_s^size Size of price-responsive demand segment s as a fraction of the hourly zonal demand [%]\noverlineOmega_yz Maximum capacity of technology y in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the maximum grid connection capacity in MW AC)\nunderlineOmega_yz Minimum capacity of technology y in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the minimum grid connection capacity in MW AC)\noverlineOmega^energy_yz Maximum energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the maximum storage component in MWh)\nunderlineOmega^energy_yz Minimum energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the minimum storage component in MWh)\noverlineOmega^charge_yz Maximum charging power capacity of technology y in zone z - only applicable for storage resources, y in mathcalO^asym [MW]\nunderlineOmega^charge_yz Minimum charging capacity of technology y in zone z- only applicable for storage resources, y in mathcalO^asym [MW]\noverlineOmega^pv_yz Maximum solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\nunderlineOmega^pv_yz Minimum solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\noverlineOmega^wind_yz Maximum wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\nunderlineOmega^wind_yz Minimum wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\noverlineOmega^inv_yz Maximum inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\nunderlineOmega^inv_yz Minimum inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\noverlineOmega^dcdis_yz Maximum storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\nunderlineOmega^dcdis_yz Minimum storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\noverlineOmega^dccha_yz Maximum storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\nunderlineOmega^dccha_yz Minimum storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\noverlineOmega^acdis_yz Maximum storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\nunderlineOmega^acdis_yz Minimum storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\noverlineOmega^accha_yz Maximum storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\nunderlineOmega^accha_yz Minimum storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [MW AC]\noverlineDelta_yz Existing installed capacity of technology y in zone z [MW] (Note that for co-located VRE and storage resources, this value represents the existing installed capacity of the grid connection in [MW AC])\noverlineDelta^energy_yz Existing installed energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [MWh] (Note that for co-located VRE and storage resources, this value represents the existing installed energy capacity of the storage component in MWh)\noverlineDelta^charge_yz Existing installed charging capacity of technology y in zone z - only applicable for storage resources, y in mathcalO [MW]\noverlineDelta^pv_yz Existing installed solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [MW DC]\noverlineDelta^wind_yz Existing installed wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [MW AC]\noverlineDelta^inv_yz Existing installed inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [MW AC]\noverlineDelta^dcdis_yz Existing installed storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [MW DC]\noverlineDelta^dccha_yz Existing installed storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [MW DC]\noverlineDelta^acdis_yz Existing installed storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [MW AC]\noverlineDelta^dccha_yz Existing installed storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymdccha [MW AC]\noverlineOmega_yz^size Unit size of technology y in zone z [MW]\npi_yz^INVEST Investment cost (annual amortization of total construction cost) for power capacity of technology y in zone z [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the grid connection capacity in $/MW AC-yr)\npi_yz^INVESTenergy Investment cost (annual amortization of total construction cost) for energy capacity of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^pv [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the investment cost of the energy capacity of the storage component in $/MWh-yr)\npi_yz^INVESTcharge Investment cost (annual amortization of total construction cost) for charging power capacity of technology y in zone z - only applicable for storage resources, y in mathcalO [$/MW-yr]\npi_yz^INVESTpv Investment cost (annual amortization of total construction cost) for solar PV capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [$/MW DC-yr]\npi_yz^INVESTwind Investment cost (annual amortization of total construction cost) for wind capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [$/MW AC-yr]\npi_yz^INVESTinv Investment cost (annual amortization of total construction cost) for inverter capacity of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [$/MW AC-yr]\npi_yz^INVESTdcdis Investment cost (annual amortization of total construction cost) for storage DC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^asymdcdis [$/MW DC-yr]\npi_yz^INVESTdccha Investment cost (annual amortization of total construction cost) for storage DC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^asymdccha [$/MW DC-yr]\npi_yz^INVESTacdis Investment cost (annual amortization of total construction cost) for storage AC discharge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^asymacdis [$/MW AC-yr]\npi_yz^INVESTaccha Investment cost (annual amortization of total construction cost) for storage AC charge capacity of technology y in zone z - only applicable for co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^asymaccha [$/MW AC-yr]\npi_yz^FOM Fixed O&M cost of technology y in zone z [$/MW-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the grid connection capacity in $/MW AC-yr)\npi_yz^FOMenergy Fixed O&M cost of energy component of technology y in zone z - only applicable for storage resources, y in mathcalO cup y in mathcalVS^stor [$/MWh-yr] (Note that for co-located VRE and storage resources, this value represents the fixed O&M cost of the storage energy capacity in $/MWh-yr)\npi_yz^FOMcharge Fixed O&M cost of charging power component of technology y in zone z - only applicable for storage resources, y in mathcalO [$/MW-yr]\npi_yz^FOMpv Fixed O&M cost of the solar PV component of technology y in zone z - only applicable for co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [$/MW DC-yr]\npi_yz^FOMwind Fixed O&M cost of the wind component of technology y in zone z - only applicable for co-located VRE and storage resources with a wind component, y in mathcalVS^wind [$/MW AC-yr]\npi_yz^FOMinv Fixed O&M cost of the inverter component of technology y in zone z - only applicable for co-located VRE and storage resources with an inverter component, y in mathcalVS^inv [$/MW AC-yr]\npi_yz^FOMdcdis Fixed O&M cost of the storage DC discharge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC discharge component, y in mathcalVS^asymdcdis [$/MW DC-yr]\npi_yz^FOMdccha Fixed O&M cost of the storage DC charge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage DC charge component, y in mathcalVS^asymdccha [$/MW DC-yr]\npi_yz^FOMacdis Fixed O&M cost of the storage AC discharge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC discharge component, y in mathcalVS^asymacdis [$/MW AC-yr]\npi_yz^FOMaccha Fixed O&M cost of the storage AC charge component of technology y in zone z - only applicable for co-located VRE and storage resources with an asymmetric storage AC charge component, y in mathcalVS^asymaccha [$/MW AC-yr]\npi_yz^VOM Variable O&M cost of technology y in zone z [$/MWh]\npi_yz^VOMcharge Variable O&M cost of charging technology y in zone z - only applicable for storage and demand flexibility resources, y in mathcalO cup mathcalDF [$/MWh]\npi_yz^VOMpv Variable O&M cost of the solar PV component of technology y in zone z - only applicable to co-located VRE and storage resources with a solar PV component, y in mathcalVS^pv [$/MWh]\npi_yz^VOMwind Variable O&M cost of the wind component of technology y in zone z - only applicable to co-located VRE and storage resources with a wind component, y in mathcalVS^wind [$/MWh]\npi_yz^VOMdcdis Variable O&M cost of the storage DC discharge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage DC discharge component, y in mathcalVS^symdc cup y in mathcalVS^asymdcdis [$/MWh]\npi_yz^VOMdccha Variable O&M cost of the storage DC charge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage DC charge component, y in mathcalVS^symdc cup y in mathcalVS^asymdccha [$/MWh]\npi_yz^VOMacdis Variable O&M cost of the storage AC discharge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage AC discharge component, y in mathcalVS^symac cup y in mathcalVS^asymacdis [$/MWh]\npi_yz^VOMaccha Variable O&M cost of the storage AC charge component of technology y in zone z - only applicable to co-located VRE and storage resources with a storage AC charge component, y in mathcalVS^symac cup y in mathcalVS^asymaccha [$/MWh]\npi_yz^FUEL Fuel cost of technology y in zone z [$/MWh]\npi_yz^START Startup cost of technology y in zone z [$/startup]\nupsilon^reg_yz Maximum fraction of capacity that a resource y in zone z can contribute to frequency regulation reserve requirements\nupsilon^rsv_yz Maximum fraction of capacity that a resource y in zone z can contribute to upward operating (spinning) reserve requirements\npi^Unmet_rsv Cost of unmet spinning reserves in [$/MW]\nepsilon^demand_reg Frequency regulation reserve requirement as a fraction of forecasted demand in each time step\nepsilon^vre_reg Frequency regulation reserve requirement as a fraction of variable renewable energy generation in each time step\nepsilon^demand_rsv Operating (spinning) reserve requirement as a fraction of forecasted demand in each time step\nepsilon^vre_rsv Operating (spinning) reserve requirement as a fraction of forecasted variable renewable energy generation in each time step\nepsilon_yz^CO_2 CO_2 emissions per unit energy produced by technology y in zone z [metric tons/MWh]\nepsilon_yzp^MinTech Equals to 1 if a generator of technology y in zone z is eligible for minimum capacity carveout policy p in mathcalP^MinTech, otherwise 0\nREQ_p^MinTech The minimum capacity requirement of minimum capacity carveout policy p in mathcalP^MinTech [MW]\nREQ_p^MaxTech The maximum capacity requirement of minimum capacity carveout policy p in mathcalP^MinTech [MW]\nepsilon_yzp^CRM Capacity derating factor of technology y in zone z for capacity reserve margin policy p in mathcalP^CRM [fraction]\nRM_zp^CRM Reserve margin of zone z of capacity reserve margin policy p in mathcalP^CRM [fraction]\nepsilon_zpmass^CO_2 Emission budget of zone z under the emission cap p in mathcalP^CO_2_mass [ million of metric tonnes]\nepsilon_zpdemand^CO_2 Maximum carbon intensity of the demand of zone z under the emission cap p in mathcalP^CO_2_demand [metric tonnes/MWh]\nepsilon_zpgen^CO_2 Maximum emission rate of the generation of zone z under the emission cap p in mathcalP^CO_2_gen [metric tonnes/MWh]\nrho_yz^min Minimum stable power output per unit of installed capacity for technology y in zone z [%]\nrho_yzt^max Maximum available generation per unit of installed capacity during time step t for technology y in zone z [%]\nrho_yzt^maxpv Maximum available generation per unit of installed capacity for the solar PV component of a co-located VRE and storage resource during time step t for technology y in zone z [%]\nrho_yzt^maxwind Maximum available generation per unit of installed capacity for the wind component of a co-located VRE and storage resource during time step t for technology y in zone z [%]\nVREIndex_yz Resource bin index for VRE technology y in zone z. VREIndex_yz=1 for the first bin, and VREIndex_yz=0 for remaining bins. Only defined for yin mathcalVRE\nvarphi^map_lz Topology of the network, for line l: varphi^map_lz=1 for start zone z, - 1 for end zone z, 0 otherwise.\nmathcalB_l DC-OPF coefficient for line l [MWh]\nDelta theta^max_l Maximum voltage phase angle difference for line l [radian]\neta_yz^loss Self discharge rate per time step per unit of installed capacity for storage technology y in zone z [%]\neta_yz^charge Single-trip efficiency of storage charging/demand deferral for technology y in zone z [%]\neta_yz^discharge Single-trip efficiency of storage (and hydro reservoir) discharging/demand satisfaction for technology y in zone z [%]\neta_yz^chargedc Single-trip efficiency of storage DC charging/demand deferral for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^dischargedc Single-trip efficiency of storage DC discharging/demand satisfaction for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^chargeac Single-trip efficiency of storage AC charging/demand deferral for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^dischargeac Single-trip efficiency of storage AC discharging/demand satisfaction for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^inverter Inverter efficiency representing losses from converting DC to AC power and vice versa for technology y in zone z for co-located VRE and storage resources [%]\neta_yz^ILRpv Inverter loading ratio (the solar PV capacity sizing to the inverter capacity built) of technology y in zone z for co-located VRE and storage resources with a solar PV component [%]\neta_yz^ILRwind Inverter loading ratio (the wind PV capacity sizing to the grid connection capacity built) of technology y in zone z for co-located VRE and storage resources with a wind component [%]\nmu_yz^stor Ratio of energy capacity to discharge power capacity for storage technology (and hydro reservoir) y in zone z [MWh/MW]\nmu_yz^dcstor Ratio of discharge power capacity to energy capacity for the storage DC component of co-located VRE and storage technology y in zone z [MW/MWh]\nmu_yz^acstor Ratio of discharge power capacity to energy capacity for the storage AC component of co-located VRE and storage technology y in zone z [MW/MWh]\nmu_yz^mathcalDF Maximum percentage of hourly demand that can be shifted by technology y in zone z [%]\nkappa_yz^up Maximum ramp-up rate per time step as percentage of installed capacity of technology y in zone z [%/hr]\nkappa_yz^down Maximum ramp-down rate per time step as percentage of installed capacity of technology y in zone z [%/hr]\ntau_yz^up Minimum uptime for thermal generator type y in zone z before new shutdown [hours].\ntau_yz^down Minimum downtime or thermal generator type y in zone z before new restart [hours].\ntau_yz^advance maximum time by which flexible demand resource can be advanced [hours]\ntau_yz^delay maximum time by which flexible demand resource can be delayed [hours]\neta_yz^dflex energy losses associated with shifting the flexible demand [%]\nmu_pz^mathcalESR share of total demand in each model zone z in mathcalESR^p that must be served by qualifying renewable energy resources y in mathcalG^ESR_p\nf(n) Mapping each modeled period n in mathcalN to corresponding representative period w in mathcalW\neta_y^electrolyzer Efficiency of the electrolyzer y in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced [MWh/t] (optional parameter)\n$ ^hydrogen_y Price of hydrogen per metric tonne for electrolyzer y [$/t] (optional parameter)\nmathcalMin kt_y Minimum annual quantity of hydrogen that must be produced by electrolyzer y in kilotonnes [kt] (optional parameter)","category":"page"},{"location":"Model_Concept_Overview/model_notation/","page":"Notation","title":"Notation","text":"","category":"page"},{"location":"Getting_Started/commercial_solvers/#Using-commercial-solvers:-Gurobi-or-CPLEX","page":"Commertial solvers","title":"Using commercial solvers: Gurobi or CPLEX","text":"","category":"section"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"If you want to use the commercial solvers Gurobi or CPLEX:","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"Make sure you have a valid license and the actual solvers for either of Gurobi or CPLEX installed on your machine\nAdd Gurobi or CPLEX to the Julia Project.","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"$ julia --project=/home/youruser/GenX\n\njulia> \n(GenX) pkg> add Gurobi\n-or-\n(GenX) pkg> add CPLEX","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"#TODO: Add instructions for adding Gurobi or CPLEX to the Julia Project with the new PR. ","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"Edit the Run.jl file to use the commercial solver. For example, to use Gurobi, you can add the following lines to the Run.jl file:","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"using Gurobi\nusing GenX\n\nrun_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)","category":"page"},{"location":"Getting_Started/commercial_solvers/","page":"Commertial solvers","title":"Commertial solvers","text":"warning: Warning\nNote that if you have not already installed the required Julia packages or you do not have a valid Gurobi license on your host machine, you will receive an error message and Run.jl will not run to completion.","category":"page"},{"location":"additional_third_party_extensions/#Additional-Third-Party-Extensions-to-GenX","page":"Third Party Extensions","title":"Additional Third Party Extensions to GenX","text":"","category":"section"},{"location":"additional_third_party_extensions/#pygenx:-Python-interface-for-GenX","page":"Third Party Extensions","title":"pygenx: Python interface for GenX","text":"","category":"section"},{"location":"additional_third_party_extensions/","page":"Third Party Extensions","title":"Third Party Extensions","text":"Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation.","category":"page"},{"location":"additional_third_party_extensions/#Simple-GenX-Case-Runner:-For-automated-sequential-batch-run-for-GenX","page":"Third Party Extensions","title":"Simple GenX Case Runner: For automated sequential batch run for GenX","text":"","category":"section"},{"location":"additional_third_party_extensions/","page":"Third Party Extensions","title":"Third Party Extensions","text":"It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner","category":"page"},{"location":"Model_Reference/Resources/must_run/#Must-Run","page":"Must Run","title":"Must Run","text":"","category":"section"},{"location":"Model_Reference/Resources/must_run/","page":"Must Run","title":"Must Run","text":"Modules = [GenX]\nPages = [\"must_run.jl\"]","category":"page"},{"location":"Model_Reference/Resources/must_run/#GenX.must_run!-Tuple{JuMP.Model, Dict, Dict}","page":"Must Run","title":"GenX.must_run!","text":"must_run!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the constraints for operation of `must-run' or non-dispatchable resources, such as rooftop solar systems that do not receive dispatch signals, run-of-river hydroelectric facilities without the ability to spill water, or cogeneration systems that must produce a fixed quantity of heat in each time step. This resource type can also be used to model baseloaded or self-committed thermal generators that do not respond to economic dispatch.\n\nFor must-run resources (yin mathcalMR) output in each time period t must exactly equal the available capacity factor times the installed capacity, not allowing for curtailment. These resources are also not eligible for contributing to frequency regulation or operating reserve requirements.\n\nbeginaligned\nTheta_yzt = rho^max_yzttimes Delta^total_yz\nhspace4 cm forall y in mathcalMR z in mathcalZt in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Tutorial-3:-K-Means-and-Time-Domain-Reduction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"A good tool to reduce computation time of GenX is to use Time-domain reduction. Time Domain Reduction is a method that selects a smaller set of time steps from the data in a way that reduces computation time while still capturing the main information of the model. In this tutorial, we go over how TDR works in GenX and how it uses K-means clustering to choose the optimal time steps. For more information on TDR in capacity expansion models, see Mallapragada et al.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Table-of-Contents","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Time Domain Reduction\nK-Means Clustering\nResults of Time Domain Reduction\nReconstruction\nExtreme Periods\nObjective Values and Representative Periods","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Time-Domain-Reduction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Time Domain Reduction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To see how Time Domain Reduction works, let's look at the Doad_data in example_systems/1_three_zones:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# First, load all packages needed\nusing DataFrames\nusing CSV\nusing VegaLite\nusing YAML\nusing PlotlyJS\nusing Plots\nusing Clustering\nusing ScikitLearn\n@sk_import datasets: (make_blobs)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"WARNING: redefinition of constant make_blobs. This may fail, cause incorrect answers, or produce other errors.\nPyObject ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"case = joinpath(\"example_systems/1_three_zones\");","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads = CSV.read(joinpath(case,\"system/Demand_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"
8760×12 DataFrame
8735 rows omitted
RowVollDemand_SegmentCost_of_Demand_Curtailment_per_MWMax_Demand_Curtailment$/MWhRep_PeriodsTimesteps_per_Rep_PeriodSub_WeightsTime_IndexDemand_MW_z1Demand_MW_z2Demand_MW_z3
String7String3String7String7String7String3String7String7Int64Int64Int64Int64
15000011120001876087601785022421070
220.90.0418002742421201012
330.550.0241100371072029969
440.20.003400469471984947
5569221977944
6670452012960
7773072087996
88754421541029
99794622691083
1010834023821137
1111857824491169
1212866624741181
1313870724871187
874987491073030641463
875087501055030131439
875187511043829811423
875287521046929901427
875387531122832061531
875487541190834011624
875587551156233021576
87568756992337971339
87578757946136211277
87588758901834521217
87598759855132811154
87608760808931061092
","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The columns to note in this file are Rep_Periods, TimeSteps_Per_Rep_Period, Time_Index, and Demand_MW_. This file shows the number of time steps used in GenX before applying TDR, i.e. every hour in a year, totaling 8,760 hours. This means that there is only one representative period, as seen in Rep_Periods.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"TDR performs a \"reduction\" into a specified number of \"representative periods\", paring down the input data into a smaller set. The representative periods are then used in the GenX algorithm in place of the entire input data to reduce computation time. The TDR algorithm selects the representative periods to be the set of data whose results in GenX best match the results of the entire input data. To do this, TDR using k-means clustering, described in the next section.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"When TDR is used, the file time_domain_reduction_settings.yml is called with a variety of specified settings, shown below:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings = YAML.load(open(joinpath(case,\"settings/time_domain_reduction_settings.yml\")))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 15 entries:\n \"IterativelyAddPeriods\" => 1\n \"ExtremePeriods\" => Dict{Any, Any}(\"Wind\"=>Dict{Any, Any}(\"System\"=>Di…\n \"UseExtremePeriods\" => 1\n \"MinPeriods\" => 8\n \"MaxPeriods\" => 11\n \"DemandWeight\" => 1\n \"ClusterFuelPrices\" => 1\n \"nReps\" => 100\n \"MultiStageConcatenate\" => 0\n \"Threshold\" => 0.05\n \"TimestepsPerRepPeriod\" => 168\n \"IterateMethod\" => \"cluster\"\n \"ScalingMethod\" => \"S\"\n \"ClusterMethod\" => \"kmeans\"\n \"WeightTotal\" => 8760","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"For descriptions of all settings, see cluster_inputs in the documentation.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads |>\n@vlplot(:line, \n x=:Time_Index, y=:Demand_MW_z1, title=\"MW Load per hour, No TDR\",\n width=600,height=400,linewidth=.01)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"(Image: svg)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"As in Tutorial 1: Configuring Settings, 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.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ = YAML.load(open((joinpath(case,\"settings/genx_settings.yml\"))))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 19 entries:\n \"NetworkExpansion\" => 1\n \"ModelingToGenerateAlternativeIterations\" => 3\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 0\n \"PrintModel\" => 0\n \"TimeDomainReduction\" => 1\n \"Trans_Loss_Segments\" => 1\n \"CapacityReserveMargin\" => 0\n \"ModelingtoGenerateAlternativeSlack\" => 0.1\n \"MethodofMorris\" => 0\n \"StorageLosses\" => 1\n \"MultiStage\" => 0\n \"OverwriteResults\" => 0\n \"UCommit\" => 2\n \"ModelingToGenerateAlternatives\" => 0\n \"MaxCapReq\" => 0\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To run GenX without TDR, we start by editing the settings to set TimeDomainReduction to 0:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ[\"TimeDomainReduction\"] = 0\ngenx_settings_TZ ## Output settings","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 13 entries:\n \"NetworkExpansion\" => 1\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 0\n \"TimeDomainReduction\" => 0\n \"Trans_Loss_Segments\" => 1\n \"CapacityReserveMargin\" => 0\n \"StorageLosses\" => 1\n \"ComputeConflicts\" => 1\n \"UCommit\" => 2\n \"MaxCapReq\" => 0\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Then we write the edited settings to the file path:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"YAML.write_file((joinpath(case,\"settings/genx_settings.yml\")), genx_settings_TZ)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"And run it using include. (Note: this process will take a few minutes):","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"@time include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"This took a little while to run, and would take even longer for larger systems. Let's see how we can get the run time down using Time Domain Reduction. The next sections go over how K-means clustering is used to perform TDR, and how to interpret the resulting files in GenX.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#K-means-clustering","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"K-means clustering","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Let's go over how TDR works. To perform TDR, GenX uses K-means clustering. K-means is an optimization method that clusters data into several groups based on their proximity to \"centers\" determined by the algorithm. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"K-means finds a set number of groups such that the variance between the distance of each point in the group to the mean of the group is minimized. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"beginalign*\nmathoparg minlimits_mathbfS sum_i = 1^k sum_x in S_i x - mu_i^2 \nendalign*","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Where mathbfS = S_1 S_k are the clusters, with x denoting the elements of the clusters, and mu_i the mean of each cluster, i.e. the mean of the distances from each point to the center of the cluster. By taking the argmin over mathbfS, the points x are clustered into groups where their distance to the center is the smallest. For more information on how k-means works, see the Wikipedia. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"GenX uses the package Clustering.jl, with documentation here. As an example, using the package ScikitLearn.jl, let's generate data that can cluster easily.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"centers = 5\nX, y = make_blobs(n_samples=50,centers=centers); # From scikit-learn\nb = DataFrame(X,:auto)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Note that clustering works for data without obvious groupings, but using blobs as an example makes k-means easier to visualize.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"plotly()\nPlots.scatter(b[!,\"x1\"],b[!,\"x2\"],legend=false,title=\"Before K-means Clustering\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Now we use the function kmeans, which is also used in src/time_domain_reduction in GenX.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"R = kmeans(transpose(Matrix(b)),centers)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"kmeans returns three outputs: assignments, centers, and counts. Assignments shows to which cluster each points belongs, centers shows where the center coordinates of each cluster are, and counts shows how many points belong to each cluster.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"println(\"Assignments = \",R.assignments)\nprintln(\"\")\nprintln(\"Counts = \",R.counts)\nprintln(\"\")\nprintln(\"Centers:\")\nR.centers","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"plotly()\nPlots.scatter(b[!,\"x1\"],b[!,\"x2\"],legend=false,marker_z=R.assignments,c=:lightrainbow,title=\"After K-means Clustering\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"In GenX, the representative periods are the centers of the clusters, each representing one week of the year. In the above example that would mean there are 52 data points gathered into 11 clusters (to see this for yourself, change make_blobs to have 52 data points and 11 clusters.)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Results-of-Time-Domain-Reduction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Results of Time Domain Reduction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To visualize the results of TDR, we'll set TDR = 1 back in the genx_settings.yml file in Example_Systems_Tutorials/SmallNewEngland/OneZone/:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ[\"TimeDomainReduction\"] = 1;","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"genx_settings_TZ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"YAML.write_file((joinpath(case,\"settings/genx_settings.yml\")), genx_settings_TZ)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"And run GenX again with TDR:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"@time include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Csv files with the results of TDR are generated automatically in a folder called TDR_results found within the same folder containing the input csv files, in this case Example_Systems_Tutorials/SmallNewEngland/OneZone. The csv files in this folder show the files used in Run.jl that have been pared down from the initial input files.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"As an example, consider the input file Fuels_data.csv:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Fuels_original = CSV.read(joinpath(case,\"system/Fuels_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Compared to TDR_Results/Fuels_data.csv:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Fuels_TDR = CSV.read(joinpath(case,\"TDR_Results/Fuels_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"As you can see, the original has all 8,760 hours, while the TDR version only has 1,848 hours.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_TDR = CSV.read(joinpath(case,\"TDR_Results/Demand_data.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The 1,848 hours are divided into 11 sections of 168 hours, with each section representing one week of the original data. The number of hours per representative period is set in time_domain_reduction_settings.yml. Also specified in the file are the minimum and maximum number of clusters we would like to have (in this case 8 and 11). The k-means algorithm will then select the number of clusters that should be sufficient to capture the GenX model in fewer time steps (in this case 11).","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Gen_TDR = CSV.read(joinpath(case,\"TDR_Results/Generators_variability.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"generators = CSV.read(joinpath(case,\"system/Generators_variability.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Below, we create arrays out of the representative weeks and plot them on the same plot used in the beginning of this tutorial. The file Period_map shows which periods (weeks) are used in TDR and which time step corresponds to each period:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Period_map = CSV.read(joinpath(case,\"TDR_Results/Period_map.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Find array of unique representative periods\nrep_periods = unique(Period_map[!,\"Rep_Period\"])\n\n# Create an array of the time steps and MW values of each representative period\nweeks_load = []\nfor i in rep_periods\n week_temp_loads = [repeat([i],168) loads[(168*i-167):168*i,\"Time_Index\"] loads[(168*i-167):168*i,\"Demand_MW_z1\"]]\n weeks_load = [weeks_load; week_temp_loads]\nend\n\n# Combine with Total (pre TDR)\nloads_plot = [repeat([\"Total\"],8760) loads[!,\"Time_Index\"] loads[!,\"Demand_MW_z1\"]];\n\n# Add column names and convert column type\nloads_with_TDR = [loads_plot; weeks_load]\nloads_with_TDR = DataFrame(loads_with_TDR ,[\"Week\",\"hour\", \"MW\"])\nloads_with_TDR[!,:hour] = convert.(Int64,loads_with_TDR[!,:hour]);\nloads_with_TDR[!,:MW] = convert.(Float64,loads_with_TDR[!,:MW]);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_with_TDR |>\n@vlplot(mark={:line},\n x={:hour,title=\"Time Step (hours)\",labels=\"Week:n\"}, y={:MW,title=\"Load (MW)\"},\n color={\"Week:n\", scale={scheme=\"paired\"},sort=\"decsending\"}, title=\"MW Load per hour with TDR Representative Weeks\",\n width=845,height=400)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"(Image: svg)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"TDR is performed for four total data sets: demand (found in Demand.csv), wind and solar (found in Generators_variability.csv), and fuel prices (found in Fuels.csv). Above is just the demand load for one of the three total nodes in the example system, which is why the data may not appear to \"represent\" all 52 weeks (notice there are fewer representative periods in the fall). Instead, the periods more accurately represent all the data time series combined, including some other parts of the data not seen in this particular plot.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Extreme-Periods-Off","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Extreme Periods Off","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"GenX has a feature called ExtremePeriods, which forces kmeans to include the highest and lowest points in the algorithm. This is done to ensure outliers are used, which is needed in planning energy capacity as the system needs to be able to account for outliers in energy needs. In the above graph, we can see that energy needs peak during the summer, and that the week with the highest load demand is included as a representative week. Let's try turning extreme periods off, and see what happens. move this up","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings[\"ExtremePeriods\"] = 0;\nYAML.write_file(joinpath(case,\"settings/genx_settings.yml\"), genx_settings_TZ);\nrm(joinpath(case,\"TDR_results\"), recursive=true) ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Loads_TDR2 = CSV.read(joinpath(case,\"TDR_Results/Load_data.csv\"),DataFrame,missingstring=\"NA\");\nPeriod_map2 = CSV.read(joinpath(case,\"TDR_Results/Period_map.csv\"),DataFrame,missingstring=\"NA\");","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"rep_periods2 = unique(Period_map2[!,\"Rep_Period\"])\n\nweeks2 = []\nfor i in rep_periods2\n week_temp = [repeat([i],168) loads[(168*i-167):168*i,\"Time_Index\"] loads[(168*i-167):168*i,\"Demand_MW_z1\"]]\n weeks2 = [weeks2; week_temp]\nend\n\nweeks2 = [weeks2 repeat([\"Off\"],1848)];","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_plotOff = [repeat([\"Total\"],8760) loads[!,\"Time_Index\"] loads[!,\"Demand_MW_z1\"] repeat([\"Off\"],8760) ];\nloads_with_TDR[!,\"Extreme_Periods\"] = repeat([\"On\"],length(loads_with_TDR[!,1]));\nloads_with_TDR2 = [loads_plotOff; weeks2]","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"loads_with_TDR2 = DataFrame(loads_with_TDR2 ,[\"Week\",\"hour\",\"MW\",\"Extreme_Periods\"])\nloads_with_TDR2[!,:hour] = convert.(Int64,loads_with_TDR2[!,:hour]);\nloads_with_TDR2[!,:MW] = convert.(Float64,loads_with_TDR2[!,:MW]);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Define a new color scheme to accomodate more periods\nmyscheme = [\"#a6cee3\",\"#a6cee3\",\"#1f78b4\",\"#b2df8a\",\"#33a02c\",\"#fb9a99\",\"#e31a1c\",\"#fdbf6f\",\"#ff7f00\",\n \"#cab2d6\",\"#6a3d9a\",\"#ffff99\",\"#b15928\",\"#b1ff00\",\"#095768\",\"#ce7e00\",\"#b4a7d6\"];\n[loads_with_TDR; loads_with_TDR2] |>\n@vlplot(mark={:line}, row=\"Extreme_Periods:n\",\n x={:hour,title=\"Time Step (hours)\",labels=\"Week:n\"}, y={:MW,title=\"Load (MW)\"},\n color={\"Week:n\", scale={scheme=\"paired\"},sort=\"decsending\"}, \n title=\"MW Load per hour with TDR Representative Weeks, Extreme Periods Off\",\n width=845,height=300)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"(Image: svg)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The first plot (with Extreme Periods off) may not have the week with the highest peak highlighted. If the week with the highest demand is highlighted, try re-running the cell with Extreme Periods Off plotting the results.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Turn Extreme Periods back on:","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings[\"ExtremePeriods\"] = 1;\nYAML.write_file(joinpath(case,\"settings/time_domain_reduction_settings.yml\"), time_domain_reduction_settings);\nrm(joinpath(case,\"TDR_results\"), recursive=true) ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Reconstruction","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Reconstruction","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Below is a plot of a reconstruction of the data using only the weeks isolated as representative periods. This is what GenX reads when it runs the solver with TDR on.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"recon = []\nrecon_noex = []\nfor i in range(1,52)\n index = Period_map[i,\"Rep_Period\"]\n recon_temp = [repeat([index],168) collect((168*i-167):168*i) loads[(168*index-167):168*index,\"Demand_MW_z1\"]]\n recon = [recon; recon_temp]\n \n index2 = Period_map2[i,\"Rep_Period\"]\n recon_noex_temp = [repeat([index2],168) collect((168*i-167):168*i) loads[(168*index2-167):168*index2,\"Demand_MW_z1\"]]\n recon_noex = [recon_noex; recon_noex_temp]\nend\n\nrecon = DataFrame(recon,[\"Week\",\"hour\", \"MW\"])\nrecon[!,:hour] = convert.(Int64,recon[!,:hour]);\nrecon[!,:MW] = convert.(Float64,recon[!,:MW]);\nrecon[!,\"Extreme_Periods\"] = repeat([\"On\"],length(recon[!,1]));\n\nrecon_noex = [recon_noex repeat([\"Off\"],8736)];\nrecon_noex = DataFrame(recon_noex,[\"Week\",\"hour\", \"MW\", \"Extreme_Periods\"])\nrecon_noex[!,:hour] = convert.(Int64,recon_noex[!,:hour]);\nrecon_noex[!,:MW] = convert.(Float64,recon_noex[!,:MW]);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"plotlyjs()\nG1 = Plots.plot(recon_noex[!,:hour], recon_noex[!,:MW], linewidth=1.7,\n xticks=0:500:9000,xlabelfontsize=8,\n yticks=0:2000:18000,yformatter =:plain,ylims=(0,18000), ylabel=\"Demand (MW)\",\n legend=false, title=\"Reconstruction, Extreme Periods Off\", hover=recon_noex[!,:Week],\n color=recon_noex[!,:Week],size=(845,800),palette=:Paired_12)\n\nG2 = Plots.plot(recon[!,:hour], recon[!,:MW], linewidth=1.7,\n xticks=0:500:9000,xlabel=\"Time Step (Hours)\",xlabelfontsize=8,\n ylims=(0,18000),yticks=0:2000:18000,yformatter =:plain,ylabel=\"Demand (MW)\",\n legend=false, title=\"Reconstruction, Extreme Periods On\",hover=recon[!,:Week],\n color=recon[!,:Week],size=(845,800),palette=:Paired_12)\n\nPlots.plot(G1,G2,layout=(2,1))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Each color represents one of the representative weeks.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The range of 8-11 representative periods was chosen by the developers because it was deemed to be the smallest set that still matches the optimal value of the data well. The next section of this Tutorial goes over how the optimal values of the data change as the number of representative periods changes.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/#Objective-Values-and-Representative-Periods","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Objective Values and Representative Periods","text":"","category":"section"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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 GenX Outputs.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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 Objective Function in the documentation. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"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 example_systems/1_three_zone with a variety of minimum and maximum total periods.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" Dict{Any, Any} with 15 entries:\n \"IterativelyAddPeriods\" => 1\n \"ExtremePeriods\" => 1\n \"UseExtremePeriods\" => 1\n \"MinPeriods\" => 8\n \"MaxPeriods\" => 11\n \"DemandWeight\" => 1\n \"ClusterFuelPrices\" => 1\n \"nReps\" => 100\n \"MultiStageConcatenate\" => 0\n \"Threshold\" => 0.05\n \"TimestepsPerRepPeriod\" => 168\n \"IterateMethod\" => \"cluster\"\n \"ScalingMethod\" => \"S\"\n \"ClusterMethod\" => \"kmeans\"\n \"WeightTotal\" => 8760","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Each time Run.jl is run, a new results folder appears in the model folder. These folders are not overwritten. So far, we've run the model three times, so we should have three results folders in the 1threezones folder, but you may have more if you've run the model more. To ensure that the following code works, we'll delete any results folders beyond the original.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"folders = cd(readdir,case)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" 10-element Vector{String}:\n \".DS_Store\"\n \"README.md\"\n \"Run.jl\"\n \"policies\"\n \"resources\"\n \"results\"\n \"results_1\"\n \"results_2\"\n \"settings\"\n \"system\"","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"for folder in folders\n if length(folder) >= 8 && folder[1:8] == \"results_\"\n rm(\"example_systems/1_three_zones/\" * folder,recursive=true) \n end\nend\n \ncd(readdir,case) ## Make sure they were deleted","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" 8-element Vector{String}:\n \".DS_Store\"\n \"README.md\"\n \"Run.jl\"\n \"policies\"\n \"resources\"\n \"results\"\n \"settings\"\n \"system\"","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"To demonstrate how the objective value changes as the number of representative periods does, we'll run GenX ten times, each with a different number of periods, and plot the objective values.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Change MinPeriods and Max Periods, run `Run.jl`\n# For simplicity, keep min and max periods the same\nrep_periods = [4, 8, 12, 24, 36, 48]\ntimes = [0.0,0.0,0.0,0.0,0.0,0.0]\n\nfor i in range(1,6)\n println(\" \")\n println(\"----------------------------------------------------\")\n println(\"Iteration \",i)\n println(\"Periods = \",rep_periods[i])\n println(\"----------------------------------------------------\")\n time_domain_reduction_settings[\"MinPeriods\"] = rep_periods[i]\n time_domain_reduction_settings[\"MaxPeriods\"] = rep_periods[i]\n if \"TDR_Results\" in cd(readdir,case)\n rm(joinpath(case,\"TDR_results\", recursive=true)) \n end\n println(\" \")\n YAML.write_file(joinpath(case,\"settings/time_domain_reduction_settings.yml\"), time_domain_reduction_settings)\n time = @elapsed include(\"example_systmes/1_three_zones/Run.jl\")\n times[i] = time\nend","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Note that as the number of periods increases, so does the time it takes to run.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Now, let's check that we have the correct Results folders and process the objecive values to plot. There should be seven results folders, including the original results.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"cd(readdir,case)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"The objective value is found in the files costs.csv and status.csv.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"status = CSV.read(joinpath(case,\"results/status.csv\"),DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":" 1×3 DataFrame\n Row Status Solve Objval\n String Float64 String\n ─────────────────────────────────────\n 1\t OPTIMAL\t53.9481\t 9762.44","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Find objective values from each results folder:\n\nOV_noTDR = CSV.read(joinpath(case,\"Results/status.csv\"),DataFrame);\nOV_RP4 = CSV.read(joinpath(case,\"Results_1/status.csv\"),DataFrame);\nOV_RP8 = CSV.read(joinpath(case,\"Results_2/status.csv\"),DataFrame);\nOV_RP12 = CSV.read(joinpath(case,\"Results_3/status.csv\"),DataFrame);\nOV_RP24 = CSV.read(joinpath(case,\"Results_4/status.csv\"),DataFrame);\nOV_RP36 = CSV.read(joinpath(case,\"Results_5/status.csv\"),DataFrame);\nOV_RP48 = CSV.read(joinpath(case,\"Results_6/status.csv\"),DataFrame);","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Isolate the objective values from the data frame\nobj_val_tot = [1 OV_noTDR[!,3]; \n 4 OV_RP4[!,3];\n 8 OV_RP8[!,3];\n 12 OV_RP12[!,3]; \n 24 OV_RP24[!,3]; \n 36 OV_RP36[!,3]; \n 48 OV_RP48[!,3]]","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Take the absolute difference between the original objective value and the new ones\nobj_val_plot = [4 abs(OV_noTDR[!,3][1]-OV_RP4[!,3][1]); \n 8 abs(OV_noTDR[!,3][1]-OV_RP8[!,3][1]); \n 12 abs(OV_noTDR[!,3][1]-OV_RP12[!,3][1]);\n 24 abs(OV_noTDR[!,3][1]-OV_RP24[!,3][1]); \n 36 abs(OV_noTDR[!,3][1]-OV_RP36[!,3][1]); \n 48 abs(OV_noTDR[!,3][1]-OV_RP48[!,3][1])]","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"# Plot the differences as a function of number of representative periods\nplotlyjs()\nPlots.scatter(obj_val_plot[:,1],obj_val_plot[:,2],hover=obj_val_plot[:,2],legend=false,xticks=obj_val_plot[:,1],\n ylabel=\"|ObjValue[1] - ObjValue[x]|\",xlabel=\"Rep Periods\",title=\"Difference in Objective Values\")\nscatter!(twinx(),obj_val_plot[:,1],times,color=:red,markeralpha=.5,label=:\"Time\",legend=:topleft,\n yaxis=(label=\"Time\"))\nygrid!(:on, :dashdot, 0.1)","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Here, we can see that while having very few representative periods produces an objective value that differs greatly from the orignal, once we reach around 12 representative periods the difference begins to taper out. Therefore, the original choice of 11 maximum periods in 1_three_zones decreases the run time of GenX significantly while while maintaining an objective value close to the original. ","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"It's important to note, however, that the difference does not always taper out, and for some systems you'll find that the error in objective value continues to decrease as the number of representative periods increases. There also is no way to know apriori what number of periods works.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"Finally, let's set TDR to have 8 and 11 min/max periods again, and delete the TDR Results folder.","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings[\"MinPeriods\"] = 8;\ntime_domain_reduction_settings[\"MaxPeriods\"] = 11;","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"time_domain_reduction_settings","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"rm(joinpath(case,\"TDR_results\", recursive=true))","category":"page"},{"location":"Tutorials/Tutorial_3_K-means_time_domain_reduction/","page":"Tutorial 3: K-Means and Time Domain Reduction","title":"Tutorial 3: K-Means and Time Domain Reduction","text":"julia rm(joinpath(case,\"TDR_results\"), recursive=true) YAML.write_file(joinpath(case,\"settings/time_domain_reduction_settings.yml\"), time_domain_reduction_settings) folders = cd(readdir,case) for folder in folders if length(folder) >= 7 && folder[1:7] == \"results\" rm(\"example_systems/1_three_zones/\" * folder,recursive=true) end end","category":"page"},{"location":"User_Guide/methodofmorris_input/#Method_of_morris_range.csv-([Example](https://github.com/GenXProject/GenX/blob/main/Example_Systems/MethodofMorrisExample/OneZone/Method_of_morris_range.csv))","page":"Method of Morris Inputs","title":"Method_of_morris_range.csv (Example)","text":"","category":"section"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"This file contains the settings parameters required to run the Method of Morris algorithm in GenX. ","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"note: Note\nThis file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"Column Name Description\nResource This column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.\nZone Integer representing zone number where the resource is located.\nLower_bound Percentage lower deviation from the nominal value\nUpper_bound Percentage upper deviation from the nominal value\nParameter Column from the Generators_data.csv file containing uncertain parameters\nGroup Group the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined\np_steps Number of steps between upper and lower bound\ntotal_num_trajectory Total number of trakectories through the design matrix\nnum_trajectory Selected number of trajectories throigh the design matrix\nlen_design_mat Length of the design matrix\npolicy Name of the policy","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"Notes:","category":"page"},{"location":"User_Guide/methodofmorris_input/","page":"Method of Morris Inputs","title":"Method of Morris Inputs","text":"Upper and lower bounds are specified in terms of percentage deviation from the nominal value.\nPercentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lower_bound and Upper_bound must be identical.\nP_steps should at least be = 1%, i.e., Upper_bound – Lower_bound < p_steps\nP_steps for parameters in one group must be identical\nTotal_num_trajectory should be around 3 to 4 times the total number of uncertain parameters\nnum_trajectory should be approximately equal to the total number of uncertain parameters\nlen_design_mat should be 1.5 to 2 times the total number of uncertain parameters\nHigher number of num_trajectory and len_design_mat would lead to higher accuracy\nUpper and lower bounds should be specified for all the resources included in the Generators_data.csv file. If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.","category":"page"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/#Configure-multi-stage-inputs","page":"Configure multi-stage inputs","title":"Configure multi stage inputs","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/","page":"Configure multi-stage inputs","title":"Configure multi-stage inputs","text":"Modules = [GenX]\nPages = [\"configure_multi_stage_inputs.jl\"]","category":"page"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/#GenX.compute_overnight_capital_cost-Tuple{Dict, Array, Array, Array}","page":"Configure multi-stage inputs","title":"GenX.compute_overnight_capital_cost","text":"function compute_overnight_capital_cost(settings_d::Dict,inv_costs_yr::Array,crp::Array,tech_wacc::Array)\n\nThis function computes overnight capital costs incured within the model horizon, assuming that annualized costs to be paid after the model horizon are fully recoverable, and so are not included in the cost computation.\n\nFor each resource y in mathcalG with annualized investment cost AIC_y and capital recovery period CRP_y, overnight capital costs OCC_y are computed as follows:\n\nbeginaligned\n OCC_y = sum^min(CRP_yH)_i=1fracAIC_y(1+WACC_y)^i\nendaligned\n\nwhere WACC_y is the technology-specific weighted average cost of capital (set by the \"WACC\" field in the Generators_data.csv or Network.csv files), H is the number of years remaining between the start of the current model stage and the model horizon (the end of the final model stage) and CRP_y is the capital recovery period for technology y (specified in Generators_data.csv).\n\ninputs:\n\nsettings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\ninv_costs_yr - array object containing annualized investment costs.\ncrp - array object of capital recovery period values.\ntech_wacc - array object containing technology-specific weighted costs of capital.\n\nNOTE: The inv_costs_yr and crp arrays must be the same length; values with the same index in each array correspond to the same resource y in mathcalG.\n\nreturns: array object containing overnight capital costs, the discounted sum of annual investment costs incured within the model horizon.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/configure_multi_stage_inputs/#GenX.configure_multi_stage_inputs-Tuple{Dict, Dict, Int64}","page":"Configure multi-stage inputs","title":"GenX.configure_multi_stage_inputs","text":"function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)\n\nThis function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:\n\nOvernight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.\nAnnualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by \"StageLength\" field in multi_stage_settings.yml).\nInternal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.\nWhen NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the \"Line_Max_Flow_Possible_MW\" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.\n\ninputs:\n\ninputs_d - dict object containing model inputs dictionary generated by load_inputs().\nsettings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\nNetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the \"NetworkExpansion\" field in genx_settings.yml.\n\nreturns: dictionary containing updated model inputs, to be used in the generate_model() method.\n\n\n\n\n\n","category":"method"},{"location":"User_Guide/model_output/#GenX-Outputs","page":"Model Outputs","title":"GenX Outputs","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"The table below summarizes the units of each output variable reported as part of the various CSV files produced after each model run. The reported units are also provided. If a result file includes time-dependent values, the value will not include the hour weight in it. An annual sum (\"AnnualSum\") column/row will be provided whenever it is possible (e.g., emissions.csv).","category":"page"},{"location":"User_Guide/model_output/#1-Default-output-files","page":"Model Outputs","title":"1 Default output files","text":"","category":"section"},{"location":"User_Guide/model_output/#1.1-capacity.csv","page":"Model Outputs","title":"1.1 capacity.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports optimal values of investment variables (except StartCap, which is an input)","category":"page"},{"location":"User_Guide/model_output/#Table-15:-Structure-of-the-capacity.csv-file","page":"Model Outputs","title":"Table 15: Structure of the capacity.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nStartCap Initial power capacity of each resource type in each zone; this is an input MW\nRetCap Retired power capacity of each resource type in each zone MW\nNewCap Installed capacity of each resource type in each zone MW\nEndCap Total power capacity of each resource type in each zone MW\nStartEnergyCap Initial energy capacity of each resource type in each zone; this is an input and applies only to storage tech. MWh\nRetEnergyCap Retired energy capacity of each resource type in each zone; applies only to storage tech. MWh\nNewEnergyCap Installed energy capacity of each resource type in each zone; applies only to storage tech. MWh\nEndEnergyCap Total installed energy capacity of each resource type in each zone; applies only to storage tech. MWh\nStartChargeCap Initial charging power capacity of STOR = 2 resource type in each zone; this is an input MW\nRetChargeCap Retired charging power capacity of STOR = 2 resource type in each zone MW\nNewChargeCap Installed charging capacity of each resource type in each zone MW\nEndChargeCap Total charging power capacity of each resource type in each zone MW","category":"page"},{"location":"User_Guide/model_output/#1.2-costs.csv","page":"Model Outputs","title":"1.2 costs.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports optimal objective function value and contribution of each term by zone.","category":"page"},{"location":"User_Guide/model_output/#Table-16:-Structure-of-the-costs.csv-file","page":"Model Outputs","title":"Table 16: Structure of the costs.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\ncTotal Total objective function value $\ncFix Total annualized investment and fixed operating & maintainenance (FOM) costs associated with all resources $\ncVar Total annual variable cost associated with all resources; includes fuel costs for thermal plants $\ncNSE Total annual cost of non-served energy $\ncStart Total annual cost of start-up of thermal power plants $\ncUnmetRsv Total annual cost of not meeting time-dependent operating reserve (spinning) requirements $\ncNetworkExp Total cost of network expansion $\ncEmissionsRevenue Total and zonal emissions revenue $\ncEmissionsCost Total an zonal emissions cost $","category":"page"},{"location":"User_Guide/model_output/#1.3-emissions.csv","page":"Model Outputs","title":"1.3 emissions.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports CO2 emissions by zone at each hour; an annual sum row will be provided. If any emission cap is present, emission prices each zone faced by each cap will be copied on top of this table with the following strucutre.","category":"page"},{"location":"User_Guide/model_output/#Table-17:-Structure-of-emission-prices-in-the-emissions.csv-file","page":"Model Outputs","title":"Table 17: Structure of emission prices in the emissions.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nCO2\\price Marginal CO2 abatement cost associated with constraint on maximum annual CO2 emissions; will be same across zones if CO2 emissions constraint is applied for the entire region and not zone-wise $/ tonne CO2.","category":"page"},{"location":"User_Guide/model_output/#1.4-nse.csv","page":"Model Outputs","title":"1.4 nse.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports non-served energy for every model zone, time step and cost-segment.","category":"page"},{"location":"User_Guide/model_output/#1.5-power.csv","page":"Model Outputs","title":"1.5 power.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports power discharged by each resource (generation, storage, demand response) in each model time step.","category":"page"},{"location":"User_Guide/model_output/#1.6-reliability.csv","page":"Model Outputs","title":"1.6 reliability.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.","category":"page"},{"location":"User_Guide/model_output/#1.7-prices.csv","page":"Model Outputs","title":"1.7 prices.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the load balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.","category":"page"},{"location":"User_Guide/model_output/#1.8-status.csv","page":"Model Outputs","title":"1.8 status.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Reports computational performance of the model and objective function related information.","category":"page"},{"location":"User_Guide/model_output/#Table-18:-Structure-of-the-status.csv-file","page":"Model Outputs","title":"Table 18: Structure of the status.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nStatus termination criteria (optimal, timelimit etc.). \nsolve Solve time including time for pre-solve seconds\nObjval Optimal objective function value $\nObjbound Best objective lower bound $\nFinalMIPGap Optimality gap at termination in case of a mixed-integer linear program (MIP gap); when using Gurobi, the lower bound and MIP gap is reported excluding constant terms (E.g. fixed cost of existing generators that cannot be retired) in the objective function and hence may not be directly usable. Fraction","category":"page"},{"location":"User_Guide/model_output/#1.9-NetRevenue.csv","page":"Model Outputs","title":"1.9 NetRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file summarizes the cost, revenue and profit for each generation technology for each region.","category":"page"},{"location":"User_Guide/model_output/#Table-19:-Stucture-of-the-NetRevenue.csv-file","page":"Model Outputs","title":"Table 19: Stucture of the NetRevenue.csv file","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"Output Description Units\nFixed_OM_cost_MW Fixed Operation and Maintenance cost of the MW capacity. $\nFixed_OM_cost_MWh Fixed Operation and Maintenance cost of the MWh capacity. Only applicable to energy storage. $\nVar_OM_cost_out Variable Operation and Maintenance cost of the power generation or discharge. $\nVar_OM_cost_in Variable Operation and Maintenance cost of the power charge/pumping. Only applicable to energy storage. $\nFuel_cost Fuel cost of the power generation. Only applicable to generation that burns fuel. $\nCharge_cost Cost of charging power (due to the payment for electricity) Only applicable to energy storage. $\nEmissionsCost Cost of buying emission credit. $\nStartCost Cost of generator start-up. $\nInv_cost_MW Cost of building MW capacity. $\nInv_cost_MWh Cost of building MWh capacity. $\nEnergyRevenue Revenue of generating power. $\nSubsidyRevenue Revenue of Min_Cap subsidy. $\nReserveMarginRevenue Revenue earned from capacity reserve margin constraints. $\nESRRevenue Revenue selling renewable/clean energy credits. $\nRevenue Total Revenue. $\nCost Total Cost. $\nProfit Revenue minus Cost. $","category":"page"},{"location":"User_Guide/model_output/#2-Settings-specific-outputs","page":"Model Outputs","title":"2 Settings-specific outputs","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This section includes the output files that GenX will print if corresponding function is specified in the Settings.","category":"page"},{"location":"User_Guide/model_output/#2.1-CapacityValue.csv","page":"Model Outputs","title":"2.1 CapacityValue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the time-dependent capacity value calculated for each generator. GenX will print this file only if the capacity reserve margin constraints are modeled through the setting file. Each row of the file (excluding the header) corresponds to a generator specified in the inputs. Each column starting from the t1 to the second last one stores the result of capacity obligation provided in each hour divided by the total capacity. Thus the number is unitless. If the capacity margin reserve is not binding for one hour, GenX will return zero. The last column specified the name of the corresponding capacity reserve constraint. Note that, if the user calculates the hour-weight-averaged capacity value for each generator using data of the binding hours, the result is what RTO/ISO call capacity credit.","category":"page"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"","category":"page"},{"location":"User_Guide/model_output/#2.2-EnergyRevenue.csv","page":"Model Outputs","title":"2.2 EnergyRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the energy revenue in $ earned by each generator through injecting into the grid. Only annual sum values are available.","category":"page"},{"location":"User_Guide/model_output/#2.3-ChargingCost.csv","page":"Model Outputs","title":"2.3 ChargingCost.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the charging cost in $ of earned by each generator through withdrawing from the grid. Only annual sum values are available.","category":"page"},{"location":"User_Guide/model_output/#2.4-ReserveMargin.csv","page":"Model Outputs","title":"2.4 ReserveMargin.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the shadow prices of the capacity reserve margin constraints. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver, as described earlier. Each row (except the header) corresponds to a capacity reserve margin constraint, and each column corresponds to an time step. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.","category":"page"},{"location":"User_Guide/model_output/#2.5-ReserveMarginRevenue.csv","page":"Model Outputs","title":"2.5 ReserveMarginRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.","category":"page"},{"location":"User_Guide/model_output/#2.6-ESR_prices.csv","page":"Model Outputs","title":"2.6 ESR_prices.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the renewable/clean energy credit price of each modeled RPS/CES constraint. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. The unit is /MWh.","category":"page"},{"location":"User_Guide/model_output/#2.7-ESR_Revenue.csv","page":"Model Outputs","title":"2.7 ESR_Revenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.","category":"page"},{"location":"User_Guide/model_output/#2.8-SubsidyRevenue.csv","page":"Model Outputs","title":"2.8 SubsidyRevenue.csv","text":"","category":"section"},{"location":"User_Guide/model_output/","page":"Model Outputs","title":"Model Outputs","text":"This file includes subsidy revenue earned if a generator specified Min_Cap is provided in the input file. GenX will print this file only the shadow price can be obtained form the solver. Do not confuse this with the Minimum Capacity Carveout constraint, which is for a subset of generators, and a separate revenue term will be calculated in other files. The unit is $.","category":"page"},{"location":"Tutorials/Tutorials_intro/#GenX-Tutorials","page":"Tutorials Overview","title":"GenX Tutorials","text":"","category":"section"},{"location":"Tutorials/Tutorials_intro/","page":"Tutorials Overview","title":"Tutorials Overview","text":"Welcome to the GenX tutorials! In the following tutorials, we outline some important features of GenX and how to run them. All the tutorials are written in Julia and are available as Jupyter notebooks at the GenX-Tutorials repository.","category":"page"},{"location":"Tutorials/Tutorials_intro/","page":"Tutorials Overview","title":"Tutorials Overview","text":"Here is a list of the tutorials:","category":"page"},{"location":"Tutorials/Tutorials_intro/","page":"Tutorials Overview","title":"Tutorials Overview","text":"Tutorial 1: Configuring Settings\nTutorial 2: Network Visualization\nTutorial 3: K-Means and Time Domain Reduction\nTutorial 4: Model Generation\nTutorial 5: Solving the Model\nTutorial 6: Solver Settings","category":"page"},{"location":"User_Guide/model_input/#GenX-Inputs","page":"Model Inputs","title":"GenX Inputs","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"All input files are in CSV format. Running the GenX model requires a minimum of five mandatory input files:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Fuels_data.csv: specify fuel type, CO2 emissions intensity, and time-series of fuel prices.\nNetwork.csv: specify network topology, transmission fixed costs, capacity and loss parameters.\nDemand_data.csv: specify time-series of demand profiles for each model zone, weights for each time step, demand shedding costs, and optional time domain reduction parameters.\nGenerators_variability.csv: specify time-series of capacity factor/availability for each resource.\nGenerators_data.csv: specify cost and performance data for generation, storage and demand flexibility resources.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Additionally, the user may need to specify eight more settings-specific input files based on model configuration and type of scenarios of interest:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Operational_reserves.csv: specify operational reserve requirements as a function of demand and renewables generation and penalty for not meeting these requirements.\nEnergy_share_requirement.csv: specify regional renewable portfolio standard and clean energy standard style policies requiring minimum energy generation from qualifying resources.\nCO2_cap.csv: specify regional CO2 emission limits.\nCapacity_reserve_margin.csv: specify regional capacity reserve margin requirements.\nMinimum_capacity_requirement.csv: specify regional minimum technology capacity deployment requirements.\nVre_and_stor_data.csv: specify cost and performance data for co-located VRE and storage resources.\nVre_and_stor_solar_variability.csv: specify time-series of capacity factor/availability for each solar PV resource that exists for every co-located VRE and storage resource (in DC terms).\nVre_and_stor_wind_variability.csv: specify time-series of capacity factor/availability for each wind resource that exists for every co-located VRE and storage resource (in AC terms).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Note\nNames of the input files are case sensitive.","category":"page"},{"location":"User_Guide/model_input/#1-Mandatory-input-data","page":"Model Inputs","title":"1 Mandatory input data","text":"","category":"section"},{"location":"User_Guide/model_input/#1.1-Fuels_data.csv","page":"Model Inputs","title":"1.1 Fuels_data.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• First row: names of all fuels used in the model instance which should match the labels used in Fuel column in one of the resource .csv file in the resources folder. For renewable resources or other resources that do not consume a fuel, the name of the fuel is None.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second row: The second row specifies the CO2 emissions intensity of each fuel in tons/MMBtu (million British thermal units). Note that by convention, tons correspond to metric tonnes and not short tons (although as long as the user is internally consistent in their application of units, either can be used).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Remaining rows: Rest of the rows in this input file specify the time-series for prices for each fuel in /MMBtu. A constant price can be specified by entering the same value for all hours.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"** First column:** The first column in this file denotes, Time_index, represents the index of time steps in a model instance.","category":"page"},{"location":"User_Guide/model_input/#1.2-Network.csv","page":"Model Inputs","title":"1.2 Network.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This input file contains input parameters related to: 1) definition of model zones (regions between which transmission flows are explicitly modeled) and 2) definition of transmission network topology, existing capacity, losses and reinforcement costs. The following table describe each of the mandatory parameter inputs need to be specified to run an instance of the model, along with comments for the model configurations when they are needed.","category":"page"},{"location":"User_Guide/model_input/#Table-3:-Structure-of-the-Network.csv-file","page":"Model Inputs","title":"Table 3: Structure of the Network.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nSettings-specific Columns \nMultiple zone model \nNetwork_Lines Numerical index for each network line. The length of this column is counted but the actual values are not used.\nz* (Network map) OR StartZone, EndZone See below\nLine_Max_Flow_MW Existing capacity of the inter-regional transmission line.\nNetworkExpansion = 1 \nLine_Max_Reinforcement_MW Maximum allowable capacity addition to the existing transmission line.\nLine_Reinforcement_Cost_per_MWyr Cost of adding new capacity to the inter-regional transmission line.\nTrans_Loss_Segments = 1 \nLine_Loss_Percentage fractional transmission loss for each transmission line\nTrans_Loss_Segments > 1 \nOhms Line resistance in Ohms (used to calculate I^2R losses)\nkV Line voltage in kV (used to calculate I^2R losses)\nCapacityReserveMargin > 0 \nCapRes_* Eligibility of the transmission line for adding firm capacity to the capacity reserve margin constraint. * represents the number of the capacity reserve margin constraint.\n 1 = the transmission line is eligible for adding firm capacity to the region\n 0 = the transmission line is not eligible for adding firm capacity to the region\nDerateCapRes_* (0,1) value represents the derating of the firm transmission capacity for the capacity reserve margin constraint.\nCapResExcl_* (-1,1,0) = -1 if the designated direction of the transmission line is inbound to locational deliverability area (LDA) modeled by the capacity reserve margin constraint. = 1 if the designated direction of the transmission line is outbound from the LDA modeled by the capacity reserve margin constraint. Zero otherwise.\nMultiStage == 1 \nCapital_Recovery_Period Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for network transmission line expansion.\nLine_Max_Flow_Possible_MW Maximum possible line flow in the current model period. Overrides Line_Max_Reinforcement_MW, which is not used when performing multi-stage modeling.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"There are two interfaces implemented for specifying the network topology itself: a matrix interface and a list interface. Only one choice is permitted in a given file.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The list interface consists of a column for the lines start zone and one for the line's end zone. Here is a snippet of the Network.csv file for a map with three zones and two lines:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Network_Lines, Start_Zone, End_Zone,\n 1, 1, 2,\n 2, 1, 3,","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The matrix interface requires N columns labeled z1, z2, z3 ... zN, and L rows, one for each network line (or interregional path), with a 1 in the column corresponding to the 'start' zone and a -1 in the column corresponding to the 'end' zone for each line. Here is the same network map implemented as a matrix:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Network_Lines, z1, z2, z3,\n 1, 1, -1, 0,\n 2, 1, 0, -1,","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Note that in either case, positive flows indicate flow from start to end zone; negative flows indicate flow from end to start zone.","category":"page"},{"location":"User_Guide/model_input/#1.3-Demand_data.csv-(Load_data.csv)","page":"Model Inputs","title":"1.3 Demand_data.csv (Load_data.csv)","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file includes parameters to characterize model temporal resolution to approximate annual grid operations, electricity demand for each time step for each zone, and cost of load shedding. Note that GenX is designed to model hourly time steps. With some care and effort, finer (e.g. 15 minute) or courser (e.g. 2 hour) time steps can be modeled so long as all time-related parameters are scaled appropriately (e.g. time period weights, heat rates, ramp rates and minimum up and down times for generators, variable costs, etc).","category":"page"},{"location":"User_Guide/model_input/#Table-4:-Structure-of-the-Demand_data.csv-file","page":"Model Inputs","title":"Table 4: Structure of the Demand_data.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMandatory Columns \nVoll Value of lost load (also referred to as non-served energy) in /MWh.\nDemand_Segment Number of demand curtailment/unserved demand segments with different cost and capacity of curtailable demand for each segment. User-specified demand segments. Integer values starting with 1 in the first row. Additional segements added in subsequent rows.\nCost_of_Demand_Curtailment_per_MW Cost of non-served energy/demand curtailment (for each segment), reported as a fraction of value of the lost load (non-served demand). If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length equal to the length of Demand_Segment.\nMax_Demand_Curtailment Maximum time-dependent demand curtailable in each segment, reported as % of the demand in each zone and each period. If Demand_Segment = 1, then this parameter is a scalar and equal to one. In general this parameter is a vector of length given by length of Demand_segment.\nTime_Index Index defining time step in the model.\nDemand_MW_z* Demand profile of a zone z* in MW; if multiple zones, this parameter will be a matrix with columns equal to number of zones (each column named appropriate zone number appended to parameter) and rows equal to number of time periods of grid operations being modeled.\nRep_Periods Number of representative periods (e.g. weeks, days) that are modeled to approximate annual grid operations. This is always a single entry. For a full-year model, this is 1.\nTimesteps_per_Rep_Period Number of timesteps per representative period (e.g. 168 if period is set as a week using hour-long time steps). This is always a single entry: all representative periods have the same length. For a full-year model, this entry is equal to the number of time steps.\nSub_Weights Number of annual time steps (e.g. hours) represented by each timestep in a representative period. The length of this column is equal to the number of representative periods. The sum of the elements should be equal to the total number of time steps in a model time horizon (e.g. 8760 hours if modeling 365 days or 8736 if modeling 52 weeks).","category":"page"},{"location":"User_Guide/model_input/#1.4-Resources-input-files","page":"Model Inputs","title":"1.4 Resources input files","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The resources folder contains the input files for each resource type. At the current version of GenX, the following resources are included in the model: ","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"thermal generators, specified in the Thermal.csv file,\nvariable renewable energy resources (VRE), specified in the VRE.csv file,\nreservoir hydro resources, specified in the Hydro.csv file,\nstorage resources, specified in the Storage.csv file,\nflexible demand resources, specified in the Flex_demand.csv file,\nmust-run resources, specified in the Must_run.csv file,\nelectrolyzers, specified in the Electrolyzer.csv file, and\nco-located VRE and storage resources, specified in the Vre_stor.csv file.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Each file contains cost and performance parameters for various generators and other resources included in the model formulation. The following table describes the mandatory columns in each of these files. Note that the column names are case insensitive.","category":"page"},{"location":"User_Guide/model_input/#Table-5a:-Mandatory-columns-in-all-resource-.csv-file","page":"Model Inputs","title":"Table 5a: Mandatory columns in all resource .csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource This column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand.\nZone Integer representing zone number where the resource is located.\nTechnology type flags \nNew_Build {0, 1}, Flag for resource (storage, generation) eligibility for capacity expansion.\n New_Build = 1: eligible for capacity expansion.\n New_Build = 0: not eligible for capacity expansion.\nCan_Retire {0, 1}, Flag for resource (storage, generation) eligibility for retirement.\n Can_Retire = 1: eligible for retirement.\n Can_Retire = 0: not eligible for retirement.\nExisting technology capacity \nExisting_Cap_MW The existing capacity of a power plant in MW. Note that for co-located VRE-STOR resources, this capacity represents the existing AC grid connection capacity in MW.\nCapacity/Energy requirements \nMax_Cap_MW -1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the maximum AC grid connection capacity in MW.\nMin_Cap_MW -1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed discharge capacity (in MW) of the resource. Note that for co-located VRE-STOR resources, this capacity represents the minimum AC grid connection capacity in MW.\nCost parameters \nInv_Cost_per_MWyr Annualized capacity investment cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this annualized capacity investment cost pertains to the grid connection.\nFixed_OM_Cost_per_MWyr Fixed operations and maintenance cost of a technology (/MW/year). Note that for co-located VRE-STOR resources, this fixed operations and maintenance cost pertains to the grid connection.\nVar_OM_Cost_per_MWh Variable operations and maintenance cost of a technology (/MWh). Note that for co-located VRE-STOR resources, these costs apply to the AC generation sent to the grid from the entire site.\nTechnical performance parameters \nHeat_Rate_MMBTU_per_MWh Heat rate of a generator or MMBtu of fuel consumed per MWh of electricity generated for export (net of on-site consumption). The heat rate is the inverse of the efficiency: a lower heat rate is better. Should be consistent with fuel prices in terms of reporting on higher heating value (HHV) or lower heating value (LHV) basis.\nFuel Fuel needed for a generator. The names should match with the ones in the Fuels_data.csv.\nRequired for writing outputs \nregion Name of the model region\ncluster Number of the cluster when representing multiple clusters of a given technology in a given region.\nRequired if electrolyzer is included in the model \nQualifiedHydrogenSupply {0,1}, Indicates that generator or storage resources is eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint)\nRequired for retrofitting \nCan_Retrofit {0, 1}, Flag for resource (storage, generation) eligibility for retrofit.\n Can_Retrofit = 1: eligible for retrofit.\n Can_Retrofit = 0: not eligible for retrofit.\nRetrofit {0, 1}, Flag for resource retrofit technologies (i.e., retrofit options, e.g. CCS retrofit for coal plants).\n Retrofit = 1: is a retrofit technology.\n Retrofit = 0: is not a retrofit technology.\nRetrofit_Id Unique identifier to group retrofittable source technologies with retrofit options inside the same zone.\nRetrofit_Efficiency [0,1], Efficiency of the retrofit technology.","category":"page"},{"location":"User_Guide/model_input/#Table-5b:-Settings-specific-columns-in-all-resource-.csv-file","page":"Model Inputs","title":"Table 5b: Settings-specific columns in all resource .csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nModelingToGenerateAlternatives = 1 \nMGA Eligibility of the technology for Modeling To Generate Alternative (MGA) run.\n 1 = Technology is available for the MGA run.\n 0 = Technology is unavailable for the MGA run (e.g. storage technologies).\nResource_Type For the MGA run, we categorize all the resources in a few resource types. We then find maximally different generation portfolio based on these resource types. For example, existing solar and new solar resources could be represented by a resource type names Solar. Categorization of resources into resource types is user dependent.\nMaintenance data \nMAINT [0,1], toggles scheduled maintenance formulation.\nMaintenance_Duration (Positive integer, less than total length of simulation.) Duration of the maintenance period, in number of timesteps. Only used if MAINT=1.\nMaintenance_Cycle_Length_Years Length of scheduled maintenance cycle, in years. 1 is maintenance every year, 3 is every three years, etc. (Positive integer. Only used if MAINT=1.)\nMaintenance_Begin_Cadence Cadence of timesteps in which scheduled maintenance can begin. 1 means that a maintenance period can start in any timestep, 24 means it can start only in timesteps 1, 25, 49, etc. A larger number can decrease the simulation computational cost as it limits the optimizer's choices. (Positive integer, less than total length of simulation. Only used if MAINT=1.)\nCO2-related parameters required if any resources have nonzero CO2CaptureFraction \nCO2_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.\nCO2_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\nBiomass {0, 1}, Flag to indicate if generator uses biomass as feedstock (optional input column).\n Biomass = 0: Not part of set (default).\n Biomass = 1: Uses biomass as fuel.\nCCS_Disposal_Cost_per_Metric_Ton Cost associated with CCS disposal (/tCO2), including pipeline, injection and storage costs of CCS-equipped generators.","category":"page"},{"location":"User_Guide/model_input/#Table-6a:-Additional-columns-in-the-Thermal.csv-file","page":"Model Inputs","title":"Table 6a: Additional columns in the Thermal.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nModel {1, 2}, Flag to indicate membership in set of thermal resources (e.g. nuclear, combined heat and power, natural gas combined cycle, coal power plant)\n Model = 1: If the power plant relies on thermal energy input and subject unit commitment constraints/decisions if UCommit >= 1 (e.g. cycling decisions/costs/constraints).\n Model = 2: If the power plant relies on thermal energy input and is subject to simplified economic dispatch constraints (ramping limits and minimum output level but no cycling decisions/costs/constraints).\nMin_Power [0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.\nRamp_Up_Percentage [0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nRamp_Dn_Percentage [0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nPiecewiseFuelUsage-related parameters \nPWFU_Fuel_Usage_Zero_Load_MMBTU_per_h The fuel usage (MMBTU/h) for the first PWFU segemnt (y-intercept) at zero load.\nPWFU_Heat_Rate_MMBTU_per_MWh_*i The slope of fuel usage function of the segment i.\nPWFU_Load_Point_MW_*i The end of segment i (MW).\nMulti-fuel parameters \nMULTI_FUELS {0, 1}, Flag to indicate membership in set of thermal resources that can burn multiple fuels at the same time (e.g., natural gas combined cycle cofiring with hydrogen, coal power plant cofiring with natural gas.\n MULTI_FUELS = 0: Not part of set (default)\n MULTI_FUELS = 1: Resources that can use fuel blending.\nNum_Fuels Number of fuels that a multi-fuel generator (MULTIFUELS = 1) can use at the same time. The length of ['Fuel1', 'Fuel2', ...] should be equal to 'Num\\Fuels'. Each fuel will requires its corresponding heat rate, min cofire level, and max cofire level.\nFuel1 Frist fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.\nFuel2 Second fuel needed for a mulit-fuel generator (MULTIFUELS = 1). The names should match with the ones in the `Fuelsdata.csv`.\nHeat1_Rate_MMBTU_per_MWh Heat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel1.\nHeat2_Rate_MMBTU_per_MWh Heat rate of a multi-fuel generator (MULTI_FUELS = 1) for Fuel2.\nFuel1_Min_Cofire_Level The minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel1_Min_CofireLevel\\Start The minimum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.\nFuel1_Max_Cofire_Level The maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel1_Max_CofireLevel\\Start The maximum blendng level of 'Fuel1' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.\nFuel2_Min_Cofire_Level The minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel2_Min_CofireLevel\\Start The minimum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.\nFuel2_Max_Cofire_Level The maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the normal generation process.\nFuel2_Max_CofireLevel\\Start The maximum blendng level of 'Fuel2' in total heat inputs of a mulit-fuel generator (MULTI_FUELS = 1) during the start-up process.","category":"page"},{"location":"User_Guide/model_input/#Table-6b:-Settings-specific-columns-in-the-Thermal.csv-file","page":"Model Inputs","title":"Table 6b: Settings-specific columns in the Thermal.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nUCommit >= 1 The following settings apply only to thermal plants with unit commitment constraints\nUp_Time Minimum amount of time a resource has to stay in the committed state.\nDown_Time Minimum amount of time a resource has to remain in the shutdown state.\nStart_Cost_per_MW Cost per MW of nameplate capacity to start a generator (/MW per start). Multiplied by the number of generation units (each with a pre-specified nameplate capacity) that is turned on.\nStart_Fuel_MMBTU_per_MW Startup fuel use per MW of nameplate capacity of each generator (MMBtu/MW per start).\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-7a:-Additional-columns-in-the-Vre.csv-file","page":"Model Inputs","title":"Table 7a: Additional columns in the Vre.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nNum_VRE_bins Number of resource availability profiles considered for each VRE resource per zone. This parameter is used to decide the number of capacity investment decision variables related to a single variable renewable energy technology in each zone.\n Num_VRE_bins = 1: using a single resource availability profile per technology per zone. 1 capacity investment decision variable and 1 generator RID tracking technology power output (and in each zone).\n Num_VRE_bins > 1: using multiple resource availability profiles per technology per zone. Num_VRE_bins capacity investment decision variables and 1 generator RID used to define technology power output at each time step (and in each zone). Example: Suppose we are modeling 3 bins of wind profiles for each zone. Then include 3 rows with wind resource names as Wind_1, Wind_2, and Wind_3 and a corresponding increasing sequence of RIDs. Set Num_VRE_bins for the generator with smallest RID, Wind_1, to be 3 and set Num_VRE_bins for the other rows corresponding to Wind_2 and Wind_3, to be zero. By setting Num_VRE_bins for Wind_2 and Wind_3, the model eliminates the power outputs variables for these generators. The power output from the technology across all bins is reported in the power output variable for the first generator. This allows for multiple bins without significantly increasing number of model variables (adding each bin only adds one new capacity variable and no operational variables). See documentation for curtailable_variable_renewable() for more.","category":"page"},{"location":"User_Guide/model_input/#Table-6b:-Settings-specific-columns-in-the-Vre.csv-file","page":"Model Inputs","title":"Table 6b: Settings-specific columns in the Vre.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-7a:-Additional-columns-in-the-Hydro.csv-file","page":"Model Inputs","title":"Table 7a: Additional columns in the Hydro.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMin_Power [0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.\nRamp_Up_Percentage [0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nRamp_Dn_Percentage [0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nHydro_Energy_to_Power_Ratio The rated number of hours of reservoir hydro storage at peak discharge power output. (hours).\nLDS {0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.\n LDS = 0: Not part of set (default)\n LDS = 1: Long duration storage resources","category":"page"},{"location":"User_Guide/model_input/#Table-7b:-Settings-specific-columns-in-the-Hydro.csv-file","page":"Model Inputs","title":"Table 7b: Settings-specific columns in the Hydro.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-8a:-Additional-columns-in-the-Storage.csv-file","page":"Model Inputs","title":"Table 8a: Additional columns in the Storage.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nModel {0, 1, 2}, Flag to indicate membership in set of storage resources and designate which type of storage resource formulation to employ.\n Model = 0: Not part of set (default)\n Model = 1: Discharging power capacity and energy capacity are the investment decision variables; symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage).\n Model = 2: Discharging, charging power capacity and energy capacity are investment variables; asymmetric charge and discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nLDS {0, 1}, Flag to indicate the resources eligible for long duration storage constraints with inter period linkage.\n LDS = 0: Not part of set (default)\n LDS = 1: Long duration storage resources\nSelf_Disch [0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs.\nEff_Up [0,1], Efficiency of charging storage.\nEff_Down [0,1], Efficiency of discharging storage.\nMin_Duration Specifies the minimum ratio of installed energy to discharged power capacity that can be installed (hours).\nMax_Duration Specifies the maximum ratio of installed energy to discharged power capacity that can be installed (hours).\nExisting technology capacity \nExisting_Cap_MWh The existing capacity of storage in MWh where Model = 1 or Model = 2.\nExisting_Charge_Cap_MW The existing charging capacity for resources where Model = 2.\nCapacity/Energy requirements \nMax_Cap_MWh -1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.\nMax_Charge_Cap_MW -1 (default) – no limit on maximum charge capacity of the resource. If non-negative, represents maximum allowed charge capacity (in MW) of the resource with Model = 2.\nMin_Cap_MWh -1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity (in MWh) of the resource with Model = 1 or Model = 2.\nMin_Charge_Cap_MW -1 (default) – no limit on minimum charge capacity of the resource. If non-negative, represents minimum allowed charge capacity (in MW) of the resource with Model = 2.\nCost parameters \nInv_Cost_per_MWhyr Annualized investment cost of the energy capacity for a storage technology (/MW/year), applicable to either Model = 1 or Model = 2.\nInv_Cost_Charge_per_MWyr Annualized capacity investment cost for the charging portion of a storage technology with Model = 2 (/MW/year).\nFixed_OM_Cost_per_MWhyr Fixed operations and maintenance cost of the energy component of a storage technology (/MWh/year).\nFixed_OM_Cost_Charge_per_MWyr Fixed operations and maintenance cost of the charging component of a storage technology of type Model = 2.\nVar_OM_Cost_per_MWhIn Variable operations and maintenance cost of the charging aspect of a storage technology with Model = 2. Otherwise 0 (/MWh).","category":"page"},{"location":"User_Guide/model_input/#Table-8b:-Settings-specific-columns-in-the-Storage.csv-file","page":"Model Inputs","title":"Table 8b: Settings-specific columns in the Storage.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Table-9:-Additional-columns-in-the-Flex_demand.csv-file","page":"Model Inputs","title":"Table 9: Additional columns in the Flex_demand.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMax_Flexible_Demand_Delay Maximum number of hours that demand can be deferred or delayed (hours).\nMax_Flexible_Demand_Advance Maximum number of hours that demand can be scheduled in advance of the original schedule (hours).\nFlexible_Demand_Energy_Eff [0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand (hours). For example, one may need to pre-cool a building more than normal to advance demand.\nCost parameters \nVar_OM_Cost_per_MWhIn Variable operations and maintenance costs associated with flexible demand deferral. Otherwise 0 (/MWh).","category":"page"},{"location":"User_Guide/model_input/#Table-10:-Additional-columns-in-the-Electrolyzer.csv-file","page":"Model Inputs","title":"Table 10: Additional columns in the Electrolyzer.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nHydrogenMWhPer_Tonne Electrolyzer efficiency in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced (MWh/t)\nElectrolyzerMinkt Minimum annual quantity of hydrogen that must be produced by electrolyzer in kilotonnes (kt)\nHydrogenPricePer_Tonne Price (or value) of hydrogen per metric tonne (/t)\nMin_Power [0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv.\nRamp_Up_Percentage [0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.\nRamp_Dn_Percentage [0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Note\nCheck Qualified_Hydrogen_Supply column in table 5a if electrolyzers are included in the model. This column is used to indicate which resources are eligible to supply electrolyzers in the same zone (used for hourly clean supply constraint).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Each co-located VRE and storage resource can be easily configured to contain either a co-located VRE-storage resource, standalone VRE resource (either wind, solar PV, or both), or standalone storage resource.","category":"page"},{"location":"User_Guide/model_input/#Table-11a:-Additional-columns-in-the-Vre_stor.csv-file","page":"Model Inputs","title":"Table 11a: Additional columns in the Vre_stor.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nTechnology type flags \nSOLAR {0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a solar PV component.\n SOLAR = 0: Not part of set (default)\n SOLAR = 1: If the co-located VRE-storage resource can produce solar PV energy.\nWIND {0, 1}, Flag to indicate membership in the set of co-located VRE-storage resources with a wind component.\n WIND = 0: Not part of set (default)\n WIND = 1: If the co-located VRE-storage resource can produce wind energy.\nSTORDCDISCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharge behind the meter and through the inverter (DC).\n STORDCDISCHARGE = 0: Not part of set (default)\n STORDCDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCDISCHARGE = 1, STORDCCHARGE = 1.\n STORDCDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nSTORDCCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge through the inverter (DC).\n STORDCCHARGE = 0: Not part of set (default)\n STORDCCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORDCCHARGE = 1, STORDCDISCHARGE = 1.\n STORDCCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nSTORACDISCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that discharges AC.\n STORACDISCHARGE = 0: Not part of set (default)\n STORACDISCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACDISCHARGE = 1, STORACCHARGE = 1.\n STORACDISCHARGE = 2: If the co-located VRE-storage resource has asymmetric discharge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nSTORACCHARGE {0, 1, 2}, Flag to indicate membership in set of co-located VRE-storage resources that charge AC.\n STORACCHARGE = 0: Not part of set (default)\n STORACCHARGE = 1: If the co-located VRE-storage resource contains symmetric charge/discharge power capacity with charging capacity equal to discharging capacity (e.g. lithium-ion battery storage). Note that if STORACCHARGE = 1, STORACDISCHARGE = 1.\n STORACCHARGE = 2: If the co-located VRE-storage resource has asymmetric charge capacities using distinct processes (e.g. hydrogen electrolysis, storage, and conversion to power using fuel cell or combustion turbine).\nLDSVRESTOR {0, 1}, Flag to indicate the co-located VRE-storage resources eligible for long duration storage constraints with inter period linkage (e.g., reservoir hydro, hydrogen storage).\n LDSVRESTOR = 0: Not part of set (default)\n LDSVRESTOR = 1: Long duration storage resources\nExisting technology capacity \nExisting_Cap_MW The existing AC grid connection capacity in MW.\nExisting_Cap_MWh The existing capacity of storage in MWh.\nExisting_Cap_Inverter_MW The existing capacity of co-located VRE-STOR resource's inverter in MW (AC).\nExisting_Cap_Solar_MW The existing capacity of co-located VRE-STOR resource's solar PV in MW (DC).\nExisting_Cap_Wind_MW The existing capacity of co-located VRE-STOR resource's wind in MW (AC).\nExisting_Cap_Discharge_DC_MW The existing discharge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_DISCHARGE = 2.\nExisting_Cap_Charge_DC_MW The existing charge capacity of co-located VRE-STOR resource's storage component in MW (DC). Note that this only applies to resources where STOR_DC_CHARGE = 2.\nExisting_Cap_Discharge_AC_MW The existing discharge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_AC_DISCHARGE = 2.\nExisting_Cap_Charge_AC_MW The existing charge capacity of co-located VRE-STOR resource's storage component in MW (AC). Note that this only applies to resources where STOR_DC_CHARGE = 2.\nCapacity/Energy requirements \nMax_Cap_MW -1 (default) – no limit on maximum discharge capacity of the resource. If non-negative, represents maximum allowed AC grid connection capacity in MW of the resource.\nMax_Cap_MWh -1 (default) – no limit on maximum energy capacity of the resource. If non-negative, represents maximum allowed energy capacity of storage in MWh.\nMin_Cap_MW -1 (default) – no limit on minimum discharge capacity of the resource. If non-negative, represents minimum allowed AC grid connection capacity in MW.\nMin_Cap_MWh -1 (default) – no limit on minimum energy capacity of the resource. If non-negative, represents minimum allowed energy capacity of storage in MWh.\nMax_Cap_Inverter_MW -1 (default) – no limit on maximum inverter capacity of the resource. If non-negative, represents maximum allowed inverter capacity (in MW AC) of the resource.\nMax_Cap_Solar_MW -1 (default) – no limit on maximum solar PV capacity of the resource. If non-negative, represents maximum allowed solar PV capacity (in MW DC) of the resource.\nMax_Cap_Wind_MW -1 (default) – no limit on maximum wind capacity of the resource. If non-negative, represents maximum allowed wind capacity (in MW AC) of the resource.\nMax_Cap_Discharge_DC_MW -1 (default) – no limit on maximum DC discharge capacity of the resource. If non-negative, represents maximum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.\nMax_Cap_Charge_DC_MW -1 (default) – no limit on maximum DC charge capacity of the resource. If non-negative, represents maximum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.\nMax_Cap_Discharge_AC_MW -1 (default) – no limit on maximum AC discharge capacity of the resource. If non-negative, represents maximum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.\nMax_Cap_Charge_AC_MW -1 (default) – no limit on maximum AC charge capacity of the resource. If non-negative, represents maximum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.\nMin_Cap_Inverter_MW -1 (default) – no limit on minimum inverter capacity of the resource. If non-negative, represents minimum allowed inverter capacity (in MW AC) of the resource.\nMin_Cap_Solar_MW -1 (default) – no limit on minimum solar PV capacity of the resource. If non-negative, represents minimum allowed solar PV capacity (in MW DC) of the resource.\nMin_Cap_Wind_MW -1 (default) – no limit on minimum wind capacity of the resource. If non-negative, represents minimum allowed wind capacity (in MW AC) of the resource.\nMin_Cap_Discharge_DC_MW -1 (default) – no limit on minimum DC discharge capacity of the resource. If non-negative, represents minimum allowed DC discharge capacity (in MW DC) of the resource with STOR_DC_DISCHARGE = 2.\nMin_Cap_Charge_DC_MW -1 (default) – no limit on minimum DC charge capacity of the resource. If non-negative, represents minimum allowed DC charge capacity (in MW DC) of the resource with STOR_DC_CHARGE = 2.\nMin_Cap_Discharge_AC_MW -1 (default) – no limit on minimum AC discharge capacity of the resource. If non-negative, represents minimum allowed AC discharge capacity (in MW AC) of the resource with STOR_AC_DISCHARGE = 2.\nMin_Cap_Charge_AC_MW -1 (default) – no limit on minimum AC charge capacity of the resource. If non-negative, represents minimum allowed AC charge capacity (in MW AC) of the resource with STOR_AC_CHARGE = 2.\nCost parameters \nInv_Cost_per_MWyr Annualized capacity investment cost of the grid connection (/MW/year).\nInv_Cost_per_MWhyr Annualized investment cost of the energy capacity for the co-located storage resource (/MW/year)\nFixed_OM_Cost_per_MWyr Fixed operations and maintenance cost of the grid connection (/MW/year).\nFixed_OM_Cost_per_MWhyr Fixed operations and maintenance cost of the energy component of the co-located storage resource. (/MWh/year).\nInv_Cost_Inverter_per_MWyr Annualized capacity investment cost of the inverter component (/MW-AC/year).\nInv_Cost_Solar_per_MWyr Annualized capacity investment cost of the solar PV component (/MW-DC/year).\nInv_Cost_Wind_per_MWyr Annualized capacity investment cost of the wind component (/MW-AC/year).\nInv_Cost_Discharge_DC_per_MWyr Annualized capacity investment cost for the discharging portion of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).\nInv_Cost_Charge_DC_per_MWyr Annualized capacity investment cost for the charging portion of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).\nInv_Cost_Discharge_AC_per_MWyr Annualized capacity investment cost for the discharging portion of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).\nInv_Cost_Charge_AC_per_MWyr Annualized capacity investment cost for the charging portion of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).\nFixed_OM_Inverter_Cost_per_MWyr Fixed operations and maintenance cost of the inverter component (/MW-AC/year).\nFixed_OM_Solar_Cost_per_MWyr Fixed operations and maintenance cost of the solar PV component (/MW-DC/year).\nFixed_OM_Wind_Cost_per_MWyr Fixed operations and maintenance cost of the wind component (/MW-AC/year).\nFixed_OM_Cost_Discharge_DC_per_MWyr Fixed operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (/MW-DC/year).\nFixed_OM_Cost_Charge_DC_per_MWyr Fixed operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (/MW-DC/year).\nFixed_OM_Cost_Discharge_AC_per_MWyr Fixed operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MW-AC/year).\nFixed_OM_Cost_Charge_AC_per_MWyr Fixed operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MW-AC/year).\nVar_OM_Cost_per_MWh_Solar Variable operations and maintenance cost of the solar PV component (multiplied by the inverter efficiency for AC terms) (/MWh).\nVar_OM_Cost_per_MWh_Wind Variable operations and maintenance cost of the wind component (/MWh).\nVar_OM_Cost_per_MWh_Discharge_DC Variable operations and maintenance cost of the discharging component of a storage technology with STOR_DC_DISCHARGE = 2 (multiplied by the inverter efficiency for AC terms) (/MWh).\nVar_OM_Cost_per_MWh_Charge_DC Variable operations and maintenance cost of the charging component of a storage technology with STOR_DC_CHARGE = 2 (divided by the inverter efficiency for AC terms) (/MWh).\nVar_OM_Cost_per_MWh_Discharge_AC Variable operations and maintenance cost of the discharging component of a storage technology with STOR_AC_DISCHARGE = 2 (/MWh).\nVar_OM_Cost_per_MWh_Charge_AC Variable operations and maintenance cost of the charging component of a storage technology with STOR_AC_CHARGE = 2 (/MWh).\nTechnical performance parameters \nSelf_Disch [0,1], The power loss of storage component of each resource per hour (fraction loss per hour).\nEtaInverter [0,1], Inverter efficiency representing losses from converting DC to AC power and vice versa for each technology\nInverterRatioSolar -1 (default) - no required ratio between solar PV capacity built to inverter capacity built. If non-negative, represents the ratio of solar PV capacity built to inverter capacity built.\nInverterRatioWind -1 (default) - no required ratio between wind capacity built to grid connection capacity built. If non-negative, represents the ratio of wind capacity built to grid connection capacity built.\nPower_to_Energy_AC The power to energy conversion for the storage component for AC discharging/charging of symmetric storage resources.\nPower_to_Energy_DC The power to energy conversion for the storage component for DC discharging/charging of symmetric storage resources.\nEff_Up_DC [0,1], Efficiency of DC charging storage – applies to storage technologies (all STOR types).\nEff_Down_DC [0,1], Efficiency of DC discharging storage – applies to storage technologies (all STOR types).\nEff_Up_AC [0,1], Efficiency of AC charging storage – applies to storage technologies (all STOR types).\nEff_Down_AC [0,1], Efficiency of AC discharging storage – applies to storage technologies (all STOR types).","category":"page"},{"location":"User_Guide/model_input/#Table-11b:-Settings-specific-columns-in-the-Vre_stor.csv-file","page":"Model Inputs","title":"Table 11b: Settings-specific columns in the Vre_stor.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nOperationalReserves = 1 \nReg_Cost Cost of providing regulation reserves (/MW per time step/hour).\nRsv_Cost Cost of providing upwards spinning or contingency reserves (/MW per time step/hour).\nReg_Max [0,1], Fraction of nameplate capacity that can committed to provided regulation reserves. .\nRsv_Max [0,1], Fraction of nameplate capacity that can committed to provided upwards spinning or contingency reserves.","category":"page"},{"location":"User_Guide/model_input/#Policy-related-columns-for-all-resources","page":"Model Inputs","title":"Policy-related columns for all resources","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"In addition to the files described above, the resources folder contains the following files that are used to specify policy-related parameters for specific resources: ","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Resource_energy_share_requirement.csv\nResource_minimum_capacity_requirement.csv\nResource_maximum_capacity_requirement.csv\nResource_capacity_reserve_margin.csv","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Note\nThese files are optional and can be omitted if no policy-related parameters are specified in the settings file. Also, not all the resources need to be included in these files, only those for which the policy applies.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"The following table describes the columns in each of these four files.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"warning: Warning\nThe first column of each file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in the policy files is not important.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if EnergyShareRequirement > 0 in the settings file. * corresponds to the ith row of the file Energy_share_requirement.csv. ","category":"page"},{"location":"User_Guide/model_input/#Table-12:-Energy-share-requirement-policy-parameters","page":"Model Inputs","title":"Table 12: Energy share requirement policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nESR_* Flag to indicate which resources are considered for the Energy Share Requirement constraint.\n 1- included\n 0- excluded\nco-located VRE-STOR resources only \nESRVreStor_* Flag to indicate which resources are considered for the Energy Share Requirement constraint.\n 1- included\n 0- excluded","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if MinCapReq = 1 in the settings file. * corresponds to the ith row of the file Minimum_capacity_requirement.csv. ","category":"page"},{"location":"User_Guide/model_input/#Table-13:-Minimum-capacity-requirement-policy-parameters","page":"Model Inputs","title":"Table 13: Minimum capacity requirement policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nMinCap\\* Flag to indicate which resources are considered for the Minimum Capacity Requirement constraint.\nco-located VRE-STOR resources only \nMinCapSolar_* Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Minimum Technology Carveout constraint.\nMinCapWind_* Eligibility of resources with a wind component to participate in Minimum Technology Carveout constraint (AC terms).\nMinCapStor_* Eligibility of resources with a storage component to participate in Minimum Technology Carveout constraint (discharge capacity in AC terms).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if MaxCapReq = 1 in the settings file. * corresponds to the ith row of the file Maximum_capacity_requirement.csv.","category":"page"},{"location":"User_Guide/model_input/#Table-14:-Maximum-capacity-requirement-policy-parameters","page":"Model Inputs","title":"Table 14: Maximum capacity requirement policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nMaxCap\\* Flag to indicate which resources are considered for the Maximum Capacity Requirement constraint.\nco-located VRE-STOR resources only \nMaxCapSolar_* Eligibility of resources with a solar PV component (multiplied by the inverter efficiency for AC terms) to participate in Maximum Technology Carveout constraint.\nMaxCapWind_* Eligibility of resources with a wind component to participate in Maximum Technology Carveout constraint (AC terms).\nMaxCapStor_* Eligibility of resources with a storage component to participate in Maximum Technology Carveout constraint (discharge capacity in AC terms).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This policy is applied when if CapacityReserveMargin > 0 in the settings file. * corresponds to the ith row of the file Capacity_reserve_margin.csv.","category":"page"},{"location":"User_Guide/model_input/#Table-15:-Capacity-reserve-margin-policy-parameters","page":"Model Inputs","title":"Table 15: Capacity reserve margin policy parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nEligibleCapRes_* Fraction of the resource capacity eligible for contributing to the capacity reserve margin constraint (e.g. derate factor).","category":"page"},{"location":"User_Guide/model_input/#Additional-module-related-columns-for-all-resources","page":"Model Inputs","title":"Additional module-related columns for all resources","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"In addition to the files described above, the resources folder can contain additional files that are used to specify attributes for specific resources and modules. Currently, the following files are supported:","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Resource_multistage_data.csv: mandatory if MultiStage = 1 in the settings file","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"warning: Warning\nThe first column of each additional module file must contain the resource name corresponding to a resource in one of the resource data files described above. Note that the order of resources in these files is not important.","category":"page"},{"location":"User_Guide/model_input/#Table-16:-Multistage-parameters","page":"Model Inputs","title":"Table 16: Multistage parameters","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"warning: Warning\nThis file is mandatory if MultiStage = 1 in the settings file.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource Resource name corresponding to a resource in one of the resource data files described above.\nCapital_Recovery_Period Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.\nLifetime Lifetime (in years) used for determining endogenous retirements of newly built capacity. Note that the same lifetime is used for each component of a co-located VRE-STOR resource.\nMin_Retired_Cap_MW Minimum required discharge capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity. Note that for co-located VRE-STOR resources, this value pertains to the grid connection.\nMin_Retired_Energy_Cap_MW Minimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing energy capacity. Note that for co-located VRE-STOR resources, this value pertains to the storage component.\nMin_Retired_Charge_Cap_MW Minimum required energy capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing charge capacity.\nContribute_Min_Retirement {0, 1}, Flag to indicate whether the (retrofitting) resource can contribute to the minimum retirement requirement.\nco-located VRE-STOR resources only \nCapital_Recovery_Period_DC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the inverter component.\nCapital_Recovery_Period_Solar Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the solar PV component.\nCapital_Recovery_Period_Wind Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the wind component.\nCapital_Recovery_PeriodDischargeDC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge DC component when STOR_DC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeDC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge DC component when STOR_DC_CHARGE = 2.\nCapital_Recovery_PeriodDischargeAC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the discharge AC component when STOR_AC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeAC Capital recovery period (in years) used for determining overnight capital costs from annualized investment costs for the charge AC component when STOR_AC_CHARGE = 2.\nMin_Retired_Cap_Inverter_MW Minimum required inverter capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_Solar_MW Minimum required solar capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_Wind_MW Minimum required wind capacity retirements in the current model period. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_DischargeDC\\MW Minimum required discharge capacity retirements in the current model period for storage resources with STOR_DC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_ChargeDC\\MW Minimum required charge capacity retirements in the current model period for storage resources with STOR_DC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_DischargeAC\\MW Minimum required discharge capacity retirements in the current model period for storage resources with STOR_AC_DISCHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nMin_Retired_Cap_ChargeAC\\MW Minimum required charge capacity retirements in the current model period for storage resources with STOR_AC_CHARGE = 2. This field can be used to enforce lifetime retirements of existing capacity.\nWACC_DC The line-specific weighted average cost of capital for the inverter component.\nWACC_Solar The line-specific weighted average cost of capital for the solar PV component.\nWACC_Wind The line-specific weighted average cost of capital for the wind component.\nWACC_Discharge_DC The line-specific weighted average cost of capital for the discharging DC storage component with STOR_DC_DISCHARGE = 2.\nWACC_Charge_DC The line-specific weighted average cost of capital for the charging DC storage component with STOR_DC_CHARGE = 2.\nWACC_Discharge_AC The line-specific weighted average cost of capital for the discharging AC storage component with STOR_AC_DISCHARGE = 2.\nWACC_Charge_AC The line-specific weighted average cost of capital for the charging AC storage component with STOR_AC_CHARGE = 2.","category":"page"},{"location":"User_Guide/model_input/#1.5-Generator_variability.csv","page":"Model Inputs","title":"1.5 Generator_variability.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the time-series of capacity factors / availability of each resource included in the resource .csv file in the resources folder for each time step (e.g. hour) modeled.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the resource .csv file in the resources folder in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in the resource .csv file must be unique. Note that for Hydro reservoir resources (i.e. Hydro.csv), values in this file correspond to inflows (in MWhs) to the hydro reservoir as a fraction of installed power capacity, rather than hourly capacity factor. Note that for co-located VRE and storage resources, solar PV and wind resource profiles should not be located in this file but rather in separate variability files (these variabilities can be in the Generators_variability.csv if time domain reduction functionalities will be utilized because the time domain reduction functionalities will separate the files after the clustering is completed).","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"|Self_Disch |[0,1], The power loss of storage technologies per hour (fraction loss per hour)- only applies to storage techs. Note that for co-located VRE-STOR resources, this value applies to the storage component of each resource.| |Min_Power |[0,1], The minimum generation level for a unit as a fraction of total capacity. This value cannot be higher than the smallest time-dependent CF value for a resource in Generators_variability.csv. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Up_Percentage |[0,1], Maximum increase in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Ramp_Dn_Percentage |[0,1], Maximum decrease in power output from between two periods (typically hours), reported as a fraction of nameplate capacity. Applies to thermal plants, and reservoir hydro resource (HYDRO = 1).| |Eff_Up |[0,1], Efficiency of charging storage – applies to storage technologies (all STOR types except co-located storage resources).| |Eff_Down |[0,1], Efficiency of discharging storage – applies to storage technologies (all STOR types except co-located storage resources). |","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"|Min_Duration |Specifies the minimum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Duration |Specifies the maximum ratio of installed energy to discharged power capacity that can be installed. Applies to STOR types 1 and 2 (hours). Note that for co-located VRE-STOR resources, this value does not apply. | |Max_Flexible_Demand_Delay |Maximum number of hours that demand can be deferred or delayed. Applies to resources with FLEX type 1 (hours). | |Max_Flexible_Demand_Advance |Maximum number of hours that demand can be scheduled in advance of the original schedule. Applies to resources with FLEX type 1 (hours). | |Flexible_Demand_Energy_Eff |[0,1], Energy efficiency associated with time shifting demand. Represents energy losses due to time shifting (or 'snap back' effect of higher consumption due to delay in use) that may apply to some forms of flexible demand. Applies to resources with FLEX type 1 (hours). For example, one may need to pre-cool a building more than normal to advance demand. |","category":"page"},{"location":"User_Guide/model_input/#1.6-Vre_and_stor_solar_variability.csv","page":"Model Inputs","title":"1.6 Vre_and_stor_solar_variability.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the time-series of capacity factors / availability of the solar PV component (DC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• first column: The first column contains the time index of each row (starting in the second row) from 1 to N.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique. ","category":"page"},{"location":"User_Guide/model_input/#1.7-Vre_and_stor_wind_variability.csv","page":"Model Inputs","title":"1.7 Vre_and_stor_wind_variability.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the time-series of capacity factors / availability of the wind component (AC capacity factors) of each co-located resource included in the Vre_and_stor_data.csv file for each time step (e.g. hour) modeled.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• First column: The first column contains the time index of each row (starting in the second row) from 1 to N.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"• Second column onwards: Resources are listed from the second column onward with headers matching each resource name in the Vre_stor.csv files in any order. The availability for each resource at each time step is defined as a fraction of installed capacity and should be between 0 and 1. Note that for this reason, resource names specified in all the resource .csv files must be unique. ","category":"page"},{"location":"User_Guide/model_input/#2.-Optional-inputs-files","page":"Model Inputs","title":"2. Optional inputs files","text":"","category":"section"},{"location":"User_Guide/model_input/#2.1-Operational_reserves.csv","page":"Model Inputs","title":"2.1 Operational_reserves.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file includes parameter inputs needed to model time-dependent procurement of regulation and spinning reserves. This file is needed if OperationalReserves flag is activated in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-7:-Structure-of-the-Operational_reserves.csv-file","page":"Model Inputs","title":"Table 7: Structure of the Operational_reserves.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nReg_Req_Percent_Demand [0,1], Regulation requirement as a percent of time-dependent demand; here demand is the total across all model zones.\nReg_Req_Percent_VRE [0,1], Regulation requirement as a percent of time-dependent wind and solar generation (summed across all model zones).\nRsv_Req_Percent_Demand [0,1], Spinning up or contingency reserve requirement as a percent of time-dependent demand (which is summed across all zones).\nRsv_Req_Percent_VRE [0,1], Spinning up or contingency reserve requirement as a percent of time-dependent wind and solar generation (which is summed across all zones).\nUnmet_Rsv_Penalty_Dollar_per_MW Penalty for not meeting time-dependent spinning reserve requirement (/MW per time step).\nDynamic_Contingency Flags to include capacity (generation or transmission) contingency to be added to the spinning reserve requirement.\nDynamic_Contingency = 1: contingency set to be equal to largest installed thermal unit (only applied when UCommit = 1).\n = 2: contingency set to be equal to largest committed thermal unit each time period (only applied when UCommit = 1).\nStatic_Contingency_MW A fixed static contingency in MW added to reserve requirement. Applied when UCommit = 1 and DynamicContingency = 0, or when UCommit = 2. Contingency term not included in operating reserve requirement when this value is set to 0 and DynamicContingency is not active.","category":"page"},{"location":"User_Guide/model_input/#2.2-Energy_share_requirement.csv","page":"Model Inputs","title":"2.2 Energy_share_requirement.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains inputs specifying minimum energy share requirement policies, such as Renewable Portfolio Standard (RPS) or Clean Energy Standard (CES) policies. This file is needed if parameter EnergyShareRequirement has a non-zero value in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Note: this file should use the same region name as specified in the the resource .csv file (inside the Resource).","category":"page"},{"location":"User_Guide/model_input/#Table-8:-Structure-of-the-Energy_share_requirement.csv-file","page":"Model Inputs","title":"Table 8: Structure of the Energy_share_requirement.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nRegion_description Region name\nNetwork_zones zone number represented as z*\nESR_* [0,1], Energy share requirements as a share of zonal demand (calculated on an annual basis). * represents the number of the ESR constraint, given by the number of ESR_* columns in the Energy_share_requirement.csv file.","category":"page"},{"location":"User_Guide/model_input/#2.3-CO2_cap.csv","page":"Model Inputs","title":"2.3 CO2_cap.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains inputs specifying CO2 emission limits policies (e.g. emissions cap and permit trading programs). This file is needed if CO2Cap flag is activated in the YAML file genx_settings.yml. CO2Cap flag set to 1 represents mass-based (tCO2 ) emission target. CO2Cap flag set to 2 is specified when emission target is given in terms of rate (tCO2/MWh) and is based on total demand met. CO2Cap flag set to 3 is specified when emission target is given in terms of rate (tCO2 /MWh) and is based on total generation.","category":"page"},{"location":"User_Guide/model_input/#Table-9:-Structure-of-the-CO2_cap.csv-file","page":"Model Inputs","title":"Table 9: Structure of the CO2_cap.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nRegion_description Region name\nNetwork_zones zone number represented as z*\nCO_2_Cap_Zone_* If a zone is eligible for the emission limit constraint, then this column is set to 1, else 0.\nCO_2_Max_tons_MWh_* Emission limit in terms of rate\nCO_2_Max_Mtons_* Emission limit in absolute values, in Million of tons\n where in the above inputs, * represents the number of the emission limit constraints. For example, if the model has 2 emission limit constraints applied separately for 2 zones, the above CSV file will have 2 columns for specifying emission limit in terms on rate: CO_2_Max_tons_MWh_1 and CO_2_Max_tons_MWh_2.","category":"page"},{"location":"User_Guide/model_input/#2.4-Capacity_reserve_margin.csv","page":"Model Inputs","title":"2.4 Capacity_reserve_margin.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the regional capacity reserve margin requirements. This file is needed if parameter CapacityReserveMargin has a non-zero value in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Note: this file should use the same region name as specified in the resource .csv file (inside the Resource).","category":"page"},{"location":"User_Guide/model_input/#Table-10:-Structure-of-the-Capacity_reserve_margin.csv-file","page":"Model Inputs","title":"Table 10: Structure of the Capacity_reserve_margin.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nRegion_description Region name\nNetwork_zones zone number represented as z*\nCapRes_* [0,1], Capacity reserve margin requirements of a zone, reported as a fraction of demand","category":"page"},{"location":"User_Guide/model_input/#2.5-Minimum_capacity_requirement.csv","page":"Model Inputs","title":"2.5 Minimum_capacity_requirement.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the minimum capacity carve-out requirement to be imposed (e.g. a storage capacity mandate or offshore wind capacity mandate). This file is needed if the MinCapReq flag has a non-zero value in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-11:-Structure-of-the-Minimum_capacity_requirement.csv-file","page":"Model Inputs","title":"Table 11: Structure of the Minimum_capacity_requirement.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMinCapReqConstraint Index of the minimum capacity carve-out requirement.\nConstraint_Description Names of minimum capacity carve-out constraints; not to be read by model, but used as a helpful notation to the model user.\nMin_MW minimum capacity requirement [MW]","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.","category":"page"},{"location":"User_Guide/model_input/#2.6-Maximum_capacity_requirement.csv","page":"Model Inputs","title":"2.6 Maximum_capacity_requirement.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This contains the maximum capacity limits to be imposed (e.g. limits on total deployment of solar, wind, or batteries in the system as a whole or in certain collections of zones). It is required if the MaxCapReq flag has a non-zero value in genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-12:-Structure-of-the-Maximum_capacity_requirement.csv-file","page":"Model Inputs","title":"Table 12: Structure of the Maximum_capacity_requirement.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nMaxCapReqConstraint Index of the maximum capacity limit.\nConstraint_Description Names of maximum capacity limit; not to be read by model, but used as a helpful notation to the model user.\nMax_MW maximum capacity limit [MW]","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Some of the columns specified in the input files in Section 2.2 and 2.1 are not used in the GenX model formulation. These columns are necessary for interpreting the model outputs and used in the output module of the GenX.","category":"page"},{"location":"User_Guide/model_input/#2.7-Method_of_morris_range.csv","page":"Model Inputs","title":"2.7 Method_of_morris_range.csv","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"This file contains the settings parameters required to run the Method of Morris algorithm in GenX. This file is needed if the MethodofMorris flag is ON in the YAML file genx_settings.yml.","category":"page"},{"location":"User_Guide/model_input/#Table-13:-Structure-of-the-Method_of_morris_range.csv-file","page":"Model Inputs","title":"Table 13: Structure of the Method_of_morris_range.csv file","text":"","category":"section"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"Column Name Description\nResource This column contains unique names of resources available to the model. Resources can include generators, storage, and flexible or time shiftable demand/loads.\nZone Integer representing zone number where the resource is located.\nLower_bound Percentage lower deviation from the nominal value\nUpper_bound Percentage upper deviation from the nominal value\nParameter Column from the resource .csv file (inside the Resource) containing uncertain parameters\nGroup Group the uncertain parameters that will be changed all at once while performing the sensitivity analysis. For example, if the fuel price of natural gas is uncertain, all generators consuming natural gas should be in the same group. Group name is user defined\np_steps Number of steps between upper and lower bound\ntotal_num_trajectory Total number of trakectories through the design matrix\nnum_trajectory Selected number of trajectories throigh the design matrix\nlen_design_mat Length of the design matrix\npolicy Name of the policy","category":"page"},{"location":"User_Guide/model_input/","page":"Model Inputs","title":"Model Inputs","text":"note: Notes\nUpper and lower bounds are specified in terms of percentage deviation from the nominal value.\nPercentage variation for uncertain parameters in a given group is identical. For example, if solar cluster 1 and solar cluster 2 both belong to the ‘solar’ group, their Lowerbound and Upperbound must be identical\nP_steps should at least be = 1\\%, i.e., Upper_bound – Lower_bound p_steps\nP_steps for parameters in one group must be identical\nTotal_num_trajectory should be around 3 to 4 times the total number of uncertain parameters\nnum_trajectory should be approximately equal to the total number of uncertain parameters\nlen_design_mat should be 1.5 to 2 times the total number of uncertain parameters\nHigher number of num_trajectory and lendesignmat would lead to higher accuracy\nUpper and lower bounds should be specified for all the resources included in the resource .csv file (inside the Resource). If a parameter related to a particular resource is not uncertain, specify upper bound = lower bound = 0.","category":"page"},{"location":"Model_Reference/methodofmorris/#Method-of-Morris","page":"Method of Morris","title":"Method of Morris","text":"","category":"section"},{"location":"Model_Reference/methodofmorris/","page":"Method of Morris","title":"Method of Morris","text":"Modules = [GenX]\nPages = [\"method_of_morris.jl\"]","category":"page"},{"location":"Model_Reference/methodofmorris/#GenX.MatSpread","page":"Method of Morris","title":"GenX.MatSpread","text":"morris(EP::Model, path::AbstractString, setup::Dict, inputs::Dict, outpath::AbstractString, OPTIMIZER)\n\nWe apply the Method of Morris developed by Morris, M., 1991 in order to identify the input parameters that produce the largest change on total system cost. Method of Morris falls under the simplest class of one-factor-at-a-time (OAT) screening techniques. It assumes l levels per input factor and generates a set of trajectories through the input space. As such, the Method of Morris generates a grid of uncertain model input parameters, x_i i=1 k,, where the range x_i^- x_i^+ of each uncertain input parameter i is split into l intervals of equal length. Each trajectory starts at different realizations of input parameters chosen at random and are built by successively selecting one of the inputs randomly and moving it to an adjacent level. These trajectories are used to estimate the mean and the standard deviation of each input parameter on total system cost. A high estimated mean indicates that the input parameter is important; a high estimated standard deviation indicates important interactions between that input parameter and other inputs.\n\n\n\n\n\n","category":"type"},{"location":"User_Guide/model_configuration/#Model-settings-parameters","page":"Model Configuration","title":"Model settings parameters","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"The first step in configuring a GenX model is to specify the model settings parameters. These parameters are specified in a genx_settings.yml file inside a settings folder which must be located in the current working directory. Settings include those related to model structure, solution strategy and outputs, policy constraints, and others. In particular:","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Model structure related settings parameters affect the formulation of the model constraints and objective function. \nComputational performance related parameters affect the accuracy of the solution.\nPolicy related parameters specify the policy type and policy goal. \nNetwork related parameters specify settings related to transmission network expansion and losses.","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Note that all settings parameters are case sensitive.","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"(Optional) The user can also select the output files that they want to export using the output_settings.yml file. This file containes a list of yes/no options for each output file, and should be located in the settings folder. By default, if output_settings.yml is not included, GenX will export all output files. ","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"The following tables summarize the model settings parameters and their default/possible values.","category":"page"},{"location":"User_Guide/model_configuration/#1.-Model-structure-related-settings-parameters","page":"Model Configuration","title":"1. Model structure related settings parameters","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nUCommit Select technical resolution of of modeling thermal generators.\n 0 = no unit commitment.\n 1 = unit commitment with integer clustering.\n 2 = unit commitment with linearized clustering.\nOperationalReserves Flag for modeling operational reserves .\n 0 = No operational reserves considered.\n 1 = Consider regulation (primary) and spinning (secondary) reserves.\nStorageLosses Flag to account for storage related losses.\n 0 = VRE and CO2 constraints DO NOT account for energy lost.\n 1 = constraints account for energy lost.\nTimeDomainReduction 1 = Use time domain reduced inputs available in the folder with the name defined by settings parameter TimeDomainReductionFolder. If such a folder does not exist or it is empty, time domain reduction will reduce the input data and save the results there.\n 0 = Use the data in the main case folder; do not perform clustering.\nTimeDomainReductionFolder Name of the folder insie the current working directory where time domain reduced input data is stored.\nVirtualChargeDischargeCost Hypothetical cost of charging and discharging storage resources (in /MWh).","category":"page"},{"location":"User_Guide/model_configuration/#2.-Solution-strategy","page":"Model Configuration","title":"2. Solution strategy","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nParameterScale Flag to turn on parameter scaling wherein demand, capacity and power variables defined in GW rather than MW. This flag aides in improving the computational performance of the model.\n 1 = Scaling is activated.\n 0 = Scaling is not activated.\nMultiStage Model multiple planning stages\n 1 = Model multiple planning stages as specified in multi_stage_settings.yml\n 0 = Model single planning stage\nModelingToGenerateAlternatives Modeling to Generate Alternative Algorithm. For details, see here\n 1 = Use the algorithm.\n 0 = Do not use the algorithm.\nModelingtoGenerateAlternativeSlack value used to define the maximum deviation from the least-cost solution as a part of Modeling to Generate Alternative Algorithm. Can take any real value between 0 and 1.\nMethodofMorris Method of Morris algorithm\n 1 = Use the algorithm.\n 0 = Do not use the algorithm.","category":"page"},{"location":"User_Guide/model_configuration/#3.-Policy-related","page":"Model Configuration","title":"3. Policy related","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nCO2Cap Flag for specifying the type of CO2 emission limit constraint.\n 0 = no CO2 emission limit\n 1 = mass-based emission limit constraint\n 2 = demand + rate-based emission limit constraint\n 3 = generation + rate-based emission limit constraint\nEnergyShareRequirement Flag for specifying regional renewable portfolio standard (RPS) and clean energy standard policy (CES) related constraints.\n Default = 0 (No RPS or CES constraints).\n 1 = activate energy share requirement related constraints.\nCapacityReserveMargin Flag for Capacity Reserve Margin constraints.\n Default = 0 (No Capacity Reserve Margin constraints)\n 1 = activate Capacity Reserve Margin related constraints\nMinCapReq Minimum technology carve out requirement constraints.\n 1 = if one or more minimum technology capacity constraints are specified\n 0 = otherwise\nMaxCapReq Maximum system-wide technology capacity limit constraints.\n 1 = if one or more maximum technology capacity constraints are specified\n 0 = otherwise","category":"page"},{"location":"User_Guide/model_configuration/#4.-Network-related","page":"Model Configuration","title":"4. Network related","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nNetworkExpansion Flag for activating or deactivating inter-regional transmission expansion.\n 1 = active\n 0 = modeling single zone or for multi-zone problems in which inter regional transmission expansion is not allowed.\nTrans_Loss_Segments Number of segments to use in piece-wise linear approximation of losses.\n 1: linear\n >=2: piece-wise quadratic","category":"page"},{"location":"User_Guide/model_configuration/#5.-Outputs","page":"Model Configuration","title":"5. Outputs","text":"","category":"section"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"Parameter Description\nPrintModel Flag for printing the model equations as .lp file.\n 1 = including the model equation as an output\n 0 = the model equation won't be included as an output\nWriteShadowPrices Get the optimal values of dual variables of various model related constraints, including to estimate electricity prices, stored value of energy and the marginal CO2 prices.\nWriteOutputs Flag for writing the model outputs with hourly resolution or just the annual sum.\n \"full\" = write the model outputs with hourly resolution.\n \"annual\" = write only the annual sum of the model outputs.","category":"page"},{"location":"User_Guide/model_configuration/","page":"Model Configuration","title":"Model Configuration","text":"The next step in configuring a GenX model is to specify the solver settings parameters using a [solver_name]_settings.yml file inside the settings folder. The solver settings parameters are solver specific and are described in the following section.","category":"page"},{"location":"Model_Reference/Resources/storage_asymmetric/#Storage-Asymmetric","page":"Storage Asymmetric","title":"Storage Asymmetric","text":"","category":"section"},{"location":"Model_Reference/Resources/storage_asymmetric/","page":"Storage Asymmetric","title":"Storage Asymmetric","text":"Modules = [GenX]\nPages = [\"storage_asymmetric.jl\"]","category":"page"},{"location":"Model_Reference/Resources/storage_asymmetric/#GenX.storage_asymmetric!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Asymmetric","title":"GenX.storage_asymmetric!","text":"storage_asymmetric!(EP::Model, inputs::Dict, setup::Dict)\n\nSets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/storage_asymmetric/#GenX.storage_asymmetric_operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Asymmetric","title":"GenX.storage_asymmetric_operational_reserves!","text":"storage_asymmetric_operational_reserves!(EP::Model, inputs::Dict)\n\nSets up variables and constraints specific to storage resources with asymmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/storage/#Storage","page":"Storage","title":"Storage","text":"","category":"section"},{"location":"Model_Reference/Resources/storage/","page":"Storage","title":"Storage","text":"GenX.storage!","category":"page"},{"location":"Model_Reference/Resources/storage/#GenX.storage!","page":"Storage","title":"GenX.storage!","text":"storage!(EP::Model, inputs::Dict, setup::Dict)\n\nA wide range of energy storage devices (all o in mathcalO) can be modeled in GenX, using one of two generic storage formulations: (1) storage technologies with symmetric charge and discharge capacity (all o in mathcalO^sym), such as Lithium-ion batteries and most other electrochemical storage devices that use the same components for both charge and discharge; and (2) storage technologies that employ distinct and potentially asymmetric charge and discharge capacities (all o in mathcalO^asym), such as most thermal storage technologies or hydrogen electrolysis/storage/fuel cell or combustion turbine systems.\n\nIf a capacity reserve margin is modeled, variables for virtual charge, Pi^CRM_ozt, and virtual discharge, Theta^CRM_ozt, are created to represent \tcontributions that a storage device makes to the capacity reserve margin without actually generating power. (This functionality can be turned off with the parameter StorageVirtualDischarge in the GenX settings file.) These represent power that the storage device could \thave discharged or consumed if called upon to do so, based on its available state of charge. Importantly, a dedicated set of variables (those of the form Pi^CRM_ozt Theta^CRM_ozt) \tand constraints are created to ensure that any virtual contributions to the capacity reserve margin could be made as actual charge/discharge if necessary without \taffecting system operations in any other timesteps. If a capacity reserve margin is not modeled, all related variables are fixed at 0. The overall contribution \tof storage devices to the system's capacity reserve margin in timestep t is equal to sum_y in mathcalO epsilon_yzp^CRM times left(Theta_yzt + Theta^CRM_ozt - Pi^CRM_ozt - Pi_yzt right), \tand includes both actual and virtual charge and discharge.\n\nbeginaligned\n\t Pi_ozt + Pi^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\n\t Pi_ozt + Pi^CRM_ozt + Theta_ozt + Theta^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\nendaligned\n\nStorage with symmetric charge and discharge capacity For storage technologies with symmetric charge and discharge capacity (all o in mathcalO^sym), charge rate, Pi_ozt, and virtual charge rate, Pi^CRM_ozt, are jointly constrained by the total installed power capacity, Omega_oz. Since storage resources generally represent a `cluster' of multiple similar storage devices of the same type/cost in the same zone, GenX permits storage resources to simultaneously charge and discharge (as some units could be charging while others discharge), with the simultaenous sum of charge, Pi_ozt, discharge, Theta_ozt, virtual charge, Pi^CRM_ozt, and virtual discharge, Theta^CRM_ozt, also limited by the total installed power capacity, Delta^total_oz. These two constraints are as follows:\n\nbeginaligned\n Pi_ozt + Pi^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\n Pi_ozt + Pi^CRM_ozt + Theta_ozt + Theta^CRM_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\nendaligned\n\nThese constraints are created with the function storage_symmetric!() in storage_symmetric.jl. If reserves are modeled, the following two constraints replace those above:\n\nbeginaligned\n Pi_ozt + Pi^CRM_ozt + f^charge_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT\n Pi_ozt + Pi^CRM_ozt + f^charge_ozt + Theta_ozt + Theta^CRM_ozt + f^discharge_ozt + r^discharge_ozt leq Delta^total_oz quad forall o in mathcalO^sym z in mathcalZ t in mathcalT \nendaligned\n\nwhere f^charge_ozt is the contribution of storage resources to frequency regulation while charging, f^discharge_ozt is the contribution of storage resources to frequency regulation while discharging, and r^discharge_ozt is the contribution of storage resources to upward reserves while discharging. Note that as storage resources can contribute to regulation and reserves while either charging or discharging, the proxy variables f^charge_ozt f^discharge_ozt and r^charge_ozt r^discharge_ozt are created for storage resources where the total contribution to regulation and reserves, f_ozt r_ozt is the sum of the proxy variables. These constraints are created with the function storage_symmetric_operational_reserves!() in storage_symmetric.jl. Storage with asymmetric charge and discharge capacity For storage technologies with asymmetric charge and discharge capacities (all o in mathcalO^asym), charge rate, Pi_ozt, is constrained by the total installed charge capacity, Delta^total charge_oz, as follows:\n\nbeginaligned\n\t Pi_ozt + Pi^CRM_ozt leq Delta^total charge_oz quad forall o in mathcalO^asym z in mathcalZ t in mathcalT\nendaligned\n\nThese constraints are created with the function storage_asymmetric() in storage_asymmetric.jl. If reserves are modeled, the above constraint is replaced by the following:\n\nbeginaligned\n\t Pi_ozt + Pi^CRM_ozt + f^charge_ozt leq Delta^total charge_oz quad forall o in mathcalO^asym z in mathcalZ t in mathcalT\nendaligned\n\nwhere f^+_y=ozt is the contribution of storage resources to frequency regulation while charging. These constraints are created with the function storage_symmetric_operational_reserves!() in storage_asymmetric.jl. All storage resources The following constraints apply to all storage resources, o in mathcalO, regardless of whether the charge/discharge capacities are symmetric or asymmetric. The following two constraints track the state of charge of the storage resources at the end of each time period, relating the volume of energy stored at the end of the time period, Gamma_ozt, to the state of charge at the end of the prior time period, Gamma_ozt-1, the charge and discharge decisions in the current time period, Pi_ozt Theta_ozt, and the self discharge rate for the storage resource (if any), eta_oz^loss. The first of these two constraints enforces storage inventory balance for interior time steps (t in mathcalT^interior), while the second enforces storage balance constraint for the initial time step (t in mathcalT^start).\n\nbeginaligned\n\t Gamma_ozt =Gamma_ozt-1 - frac1eta_oz^dischargeTheta_ozt + eta_oz^chargePi_ozt - eta_oz^lossGamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^interior\n\t Gamma_ozt =Gamma_ozt+tau^period-1 - frac1eta_oz^dischargeTheta_ozt + eta_oz^chargePi_ozt - eta_oz^lossGamma_ozt+tau^period-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^start\nendaligned\n\nIf a capacity reserve margin is modeled, then the following constraints track the relationship between the virtual charge, Pi^CRM_ozt, and virtual discharge, Theta^CRM_ozt, variables and a third variable, Gamma^CRM_ozt, representing the amount of state of charge that must be held in reserve to enable these virtual capacity reserve margin contributions, ensuring that the storage device could deliver its pledged capacity if called upon to do so without affecting its operations in other timesteps. Gamma^CRM_ozt is tracked similarly to the devices overall state of charge based on its value in the previous timestep and the virtual charge and discharge in the current timestep. Unlike the regular state of charge, virtual discharge Theta^CRM_ozt increases Gamma^CRM_ozt (as more charge must be held in reserve to support more virtual discharge), and Pi^CRM_ozt reduces Gamma^CRM_ozt.\n\nbeginaligned\n\t Gamma^CRM_ozt =Gamma^CRM_ozt-1 + frac1eta_oz^dischargeTheta^CRM_ozt - eta_oz^chargePi^CRM_ozt - eta_oz^lossGamma^CRM_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^interior\n\t Gamma^CRM_ozt =Gamma^CRM_ozt+tau^period-1 + frac1eta_oz^dischargeTheta^CRM_ozt - eta_oz^chargePi^CRM_ozt - eta_oz^lossGamma^CRM_ozt+tau^period-1 quad forall o in mathcalO z in mathcalZ t in mathcalT^start\nendaligned\n\nThe energy held in reserve, Gamma^CRM_ozt, also acts as a lower bound on the overall state of charge Gamma_ozt. This ensures that the storage device cannot use state of charge that would not have been available had it been called on to actually contribute its pledged virtual discharge at some earlier timestep. This relationship is described by the following equation:\n\nbeginaligned\n\t Gamma_ozt geq Gamma^CRM_ozt \nendaligned\n\nWhen modeling the entire year as a single chronological period with total number of time steps of tau^period, storage inventory in the first time step is linked to storage inventory at the last time step of the period representing the year. Alternatively, when modeling the entire year with multiple representative periods, this constraint relates storage inventory in the first timestep of the representative period with the inventory at the last time step of the representative period, where each representative period is made of tau^period time steps. In this implementation, energy exchange between representative periods is not permitted. When modeling representative time periods, GenX enables modeling of long duration energy storage which tracks state of charge (and state of charge held in reserve, if a capacity reserve margin is being modeled) between representative periods enable energy to be moved throughout the year. If there is more than one representative period and LDS has been enabled for resources in Generators.csv, this function calls long_duration_storage() in long_duration_storage.jl to enable this feature. The next constraint limits the volume of energy stored at any time, Gamma_ozt, to be less than the installed energy storage capacity, Delta^total energy_oz. Finally, the maximum combined discharge and virtual discharge rate for storage resources, Pi_ozt + Pi^CRM_ozt, is constrained to be less than the discharge power capacity, Omega_ozt or the state of charge at the end of the last period, Gamma_ozt-1, whichever is less.\n\nbeginaligned\n\t Gamma_ozt leq Delta^total energy_oz quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt + Theta^CRM_ozt leq Delta^total_oz quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt + Theta^CRM_ozt leq Gamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nThe above constraints are established in storage_all!() in storage_all.jl. If reserves are modeled, two pairs of proxy variables f^charge_ozt f^discharge_ozt and r^charge_ozt r^discharge_ozt are created for storage resources, to denote the contribution of storage resources to regulation or reserves while charging or discharging, respectively. The total contribution to regulation and reserves, f_ozt r_ozt is then the sum of the proxy variables:\n\nbeginaligned\n\t f_ozt = f^charge_ozt + f^dicharge_ozt quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t r_ozt = r^charge_ozt + r^dicharge_ozt quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nThe total storage contribution to frequency regulation (f_ozt) and reserves (r_ozt) are each limited specified fraction of installed discharge power capacity (upsilon^reg_yz upsilon^rsv_yz), reflecting the maximum ramp rate for the storage resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nbeginaligned\n\tf_yzt leq upsilon^reg_yz times Delta^total_yz\n\thspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT \n\tr_yz t leq upsilon^rsv_yztimes Delta^total_yz\n\thspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT\n\tendaligned\n\nWhen charging, reducing the charge rate is contributing to upwards reserve and frequency regulation as it drops net demand. As such, the sum of the charge rate plus contribution to regulation and reserves up must be greater than zero. Additionally, the discharge rate plus the contribution to regulation must be greater than zero.\n\nbeginaligned\n\t Pi_ozt - f^charge_ozt - r^charge_ozt geq 0 quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt - f^discharge_ozt geq 0 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nAdditionally, when reserves are modeled, the maximum charge rate, virtual charge rate, and contribution to regulation while charging can be no greater than the available energy storage capacity, or the difference between the total energy storage capacity, Delta^total energy_oz, and the state of charge at the end of the previous time period, Gamma_ozt-1, while accounting for charging losses eta_oz^charge. Note that for storage to contribute to reserves down while charging, the storage device must be capable of increasing the charge rate (which increase net load).\n\nbeginaligned\n\t eta_oz^charge times (Pi_ozt + Pi^CRM_ozt + f^charge_ozt) leq Delta^energy total_oz - Gamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nFinally, the constraints on maximum discharge rate are replaced by the following, to account for capacity contributed to regulation and reserves:\n\nbeginaligned\n\t Theta_ozt + Theta^CRM_ozt + f^discharge_ozt + r^discharge_ozt leq Delta^total_oz quad forall o in mathcalO z in mathcalZ t in mathcalT\n\t Theta_ozt + Theta^CRM_ozt + f^discharge_ozt + r^discharge_ozt leq Gamma_ozt-1 quad forall o in mathcalO z in mathcalZ t in mathcalT\nendaligned\n\nThe above reserve related constraints are established by storage_all_operational_reserves!() in storage_all.jl\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/#Multi-stage-investment-planning","page":"Multi-Stage Modeling Introduction","title":"Multi-stage investment planning","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"Added in 0.3","category":"page"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"GenX can be used to study the long-term evolution of the power system across multiple investment stages, in the following two ways:","category":"page"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here. This algorithm splits up a multi-stage investment planning problem into multiple, single-period sub-problems. Each period is solved iteratively as a separate linear program sub-problem (“forward pass”), and information from future periods is shared with past periods (“backwards pass”) so that investment decisions made in subsequent iterations reflect the contributions of present-day investments to future costs. The decomposition algorithm adapts previous nested Benders methods by handling integer and continuous state variables, although at the expense of losing its finite convergence property due to potential duality gap.\nThe user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as \"myopic\" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.","category":"page"},{"location":"Model_Reference/Multi_Stage/multi_stage_overview/","page":"Multi-Stage Modeling Introduction","title":"Multi-Stage Modeling Introduction","text":"More information on this feature can be found in the section Multi-stage setup.","category":"page"},{"location":"Model_Reference/write_outputs/#Functions-for-Writing-the-Different-Results/Outputs-to-Separate-Files","page":"Outputs Functions","title":"Functions for Writing the Different Results/Outputs to Separate Files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_outputs.jl\", \"choose_output_dir.jl\", \"dftranspose.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_annual-Tuple{AbstractString, DataFrames.DataFrame}","page":"Outputs Functions","title":"GenX.write_annual","text":"write_annual(fullpath::AbstractString, dfOut::DataFrame)\n\nInternal function for writing annual outputs. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.write_fulltimeseries-Tuple{AbstractString, Matrix{Float64}, DataFrames.DataFrame}","page":"Outputs Functions","title":"GenX.write_fulltimeseries","text":"write_fulltimeseries(fullpath::AbstractString, dataOut::Matrix{Float64}, dfOut::DataFrame)\n\nInternal function for writing full time series outputs. This function wraps the instructions for creating the full time series output files. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.write_outputs-Tuple{JuMP.Model, AbstractString, Dict, Dict}","page":"Outputs Functions","title":"GenX.write_outputs","text":"write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nFunction for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.choose_output_dir-Tuple{String}","page":"Outputs Functions","title":"GenX.choose_output_dir","text":"path = choose_output_dir(pathinit)\n\nAvoid overwriting (potentially important) existing results by appending to the directory name\n\nChecks if the suggested output directory already exists. While yes, it appends _1, _2, etc till an unused name is found\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.dftranspose-Tuple{DataFrames.DataFrame, Bool}","page":"Outputs Functions","title":"GenX.dftranspose","text":"df = dftranspose(df::DataFrame, withhead::Bool)\n\nReturns a transpose of a Dataframe.\n\nFIXME: This is for DataFrames@0.20.2, as used in GenX. Versions 0.21+ could use stack and unstack to make further changes while retaining the order\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Status","page":"Outputs Functions","title":"Write Status","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_status.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_status-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_status","text":"write_status(path::AbstractString, inputs::Dict, EP::Model)\n\nFunction for writing the final solve status of the optimization problem solved.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-CO_2-Cap","page":"Outputs Functions","title":"Write CO_2 Cap","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_co2_cap","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_co2_cap","page":"Outputs Functions","title":"GenX.write_co2_cap","text":"write_co2_cap(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting carbon price associated with carbon cap constraints.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Costs","page":"Outputs Functions","title":"Write Costs","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_costs.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_costs-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_costs","text":"write_costs(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the costs pertaining to the objective function (fixed, variable O&M etc.).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Fuel-Consumption","page":"Outputs Functions","title":"Write Fuel Consumption","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_fuel_consumption","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_fuel_consumption","page":"Outputs Functions","title":"GenX.write_fuel_consumption","text":"write_fuel_consumption(path::AbstractString, inputs::Dict, setup::Dict, EP::Model).\n\nWrite fuel consumption of each power plant. \n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Emissions","page":"Outputs Functions","title":"Write Emissions","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_emissions.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_emissions-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_emissions","text":"write_emissions(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting time-dependent CO_2 emissions by zone.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacities","page":"Outputs Functions","title":"Write Capacities","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_capacity.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_capacity-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_capacity","text":"write_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model))\n\nFunction for writing the diferent capacities for the different generation technologies (starting capacities or, existing capacities, retired capacities, and new-built capacities).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacity-Value-#-TODO:-add-it","page":"Outputs Functions","title":"Write Capacity Value # TODO: add it","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_capacity_value.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.capacity_reserve_margin_price-Tuple{JuMP.Model, Dict, Dict, Int64}","page":"Outputs Functions","title":"GenX.capacity_reserve_margin_price","text":"capacity_reserve_margin_price(EP::Model,\n inputs::Dict,\n setup::Dict,\n capres_zone::Int)::Vector{Float64}\n\nMarginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.\n\nReturns a vector, with units of $/MW\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacity-Factors","page":"Outputs Functions","title":"Write Capacity Factors","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_capacityfactor.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_capacityfactor-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_capacityfactor","text":"write_capacityfactor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the capacity factor of different resources. For co-located VRE-storage resources, this value is calculated if the site has either or both a solar PV or wind resource.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Charge-Values","page":"Outputs Functions","title":"Write Charge Values","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_charge.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_charge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_charge","text":"write_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the charging energy values of the different storage technologies.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Non-served-energy","page":"Outputs Functions","title":"Write Non-served-energy","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_nse.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_nse-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_nse","text":"write_nse(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting non-served energy for every model zone, time step and cost-segment.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Storage-State-of-Charge","page":"Outputs Functions","title":"Write Storage State of Charge","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_storage.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_storage-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_storage","text":"write_storage(path::AbstractString, inputs::Dict,setup::Dict, EP::Model)\n\nFunction for writing the capacities of different storage technologies, including hydro reservoir, flexible storage tech etc.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Storage-Dual","page":"Outputs Functions","title":"Write Storage Dual","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_storagedual.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_storagedual-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_storagedual","text":"write_storagedual(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting dual of storage level (state of charge) balance of each resource in each time step.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Power","page":"Outputs Functions","title":"Write Power","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_power.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_power-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_power","text":"write_power(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the different values of power generated by the different technologies in operation.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Curtailment","page":"Outputs Functions","title":"Write Curtailment","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_curtailment.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_curtailment-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_curtailment","text":"write_curtailment(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the curtailment values of the different variable renewable resources (both standalone and \tco-located).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Prices","page":"Outputs Functions","title":"Write Prices","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_price.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.locational_marginal_price-Tuple{JuMP.Model, Dict, Dict}","page":"Outputs Functions","title":"GenX.locational_marginal_price","text":"locational_marginal_price(EP::Model, inputs::Dict, setup::Dict)\n\nMarginal electricity price for each model zone and time step. This is equal to the dual variable of the power balance constraint. When solving a linear program (i.e. linearized unit commitment or economic dispatch) this output is always available; when solving a mixed integer linear program, this can be calculated only if WriteShadowPrices is activated.\n\nReturns a matrix of size (T, Z).\nValues have units of $/MWh\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#GenX.write_price-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_price","text":"write_price(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting marginal electricity price for each model zone and time step. Marginal electricity price is equal to the dual variable of the power balance constraint. If GenX is configured as a mixed integer linear program, then this output is only generated if WriteShadowPrices flag is activated. If configured as a linear program (i.e. linearized unit commitment or economic dispatch) then output automatically available.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Reliability","page":"Outputs Functions","title":"Write Reliability","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_reliability.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_reliability-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_reliability","text":"write_reliability(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting dual variable of maximum non-served energy constraint (shadow price of reliability constraint) for each model zone and time step.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Energy-Revenue","page":"Outputs Functions","title":"Write Energy Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_energy_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_energy_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_energy_revenue","text":"write_energy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing energy revenue from the different generation technologies.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Subsidy-Revenue","page":"Outputs Functions","title":"Write Subsidy Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_subsidy_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_subsidy_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_subsidy_revenue","text":"write_subsidy_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting subsidy revenue earned if a generator specified Min_Cap is provided in the input file, or if a generator is subject to a Minimum Capacity Requirement constraint. The unit is $.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Operating-Reserve-and-Regulation-Revenue","page":"Outputs Functions","title":"Write Operating Reserve and Regulation Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_operating_reserve_price_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_operating_reserve_regulation_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_operating_reserve_regulation_revenue","text":"write_operating_reserve_regulation_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting the operating reserve and regulation revenue earned by generators listed in the input file. GenX will print this file only when operating reserve and regulation are modeled and the shadow price can be obtained from the solver. The revenues are calculated as the operating reserve and regulation contributions in each time step multiplied by the corresponding shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all operating reserve and regulation constraints. As a reminder, GenX models the operating reserve and regulation at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Capacity-Revenue","page":"Outputs Functions","title":"Write Capacity Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_reserve_margin_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_reserve_margin_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_reserve_margin_revenue","text":"write_reserve_margin_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting the capacity revenue earned by each generator listed in the input file. GenX will print this file only when capacity reserve margin is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue from each capacity reserve margin constraint. The revenue is calculated as the capacity contribution of each time steps multiplied by the shadow price, and then the sum is taken over all modeled time steps. The last column is the total revenue received from all capacity reserve margin constraints. As a reminder, GenX models the capacity reserve margin (aka capacity market) at the time-dependent level, and each constraint either stands for an overall market or a locality constraint.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Energy-Share-Requirement-Revenue","page":"Outputs Functions","title":"Write Energy Share Requirement Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_esr_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_esr_revenue-Tuple{AbstractString, Dict, Dict, DataFrames.DataFrame, DataFrames.DataFrame, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_esr_revenue","text":"write_esr_revenue(path::AbstractString, inputs::Dict, setup::Dict, dfPower::DataFrame, dfESR::DataFrame, EP::Model)\n\nFunction for reporting the renewable/clean credit revenue earned by each generator listed in the input file. GenX will print this file only when RPS/CES is modeled and the shadow price can be obtained form the solver. Each row corresponds to a generator, and each column starting from the 6th to the second last is the total revenue earned from each RPS constraint. The revenue is calculated as the total annual generation (if elgible for the corresponding constraint) multiplied by the RPS/CES price. The last column is the total revenue received from all constraint. The unit is $.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Net-Revenue","page":"Outputs Functions","title":"Write Net Revenue","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_net_revenue.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_net_revenue-Tuple{AbstractString, Dict, Dict, JuMP.Model, Vararg{DataFrames.DataFrame, 11}}","page":"Outputs Functions","title":"GenX.write_net_revenue","text":"write_net_revenue(path::AbstractString, inputs::Dict, setup::Dict, EP::Model, dfCap::DataFrame, dfESRRev::DataFrame, dfResRevenue::DataFrame, dfChargingcost::DataFrame, dfPower::DataFrame, dfEnergyRevenue::DataFrame, dfSubRevenue::DataFrame, dfRegSubRevenue::DataFrame, dfVreStor::DataFrame, dfOpRegRevenue::DataFrame, dfOpRsvRevenue::DataFrame)\n\nFunction for writing net revenue of different generation technologies.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-Co-Located-VRE-and-Storage-files","page":"Outputs Functions","title":"Write Co-Located VRE and Storage files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_vre_stor\nGenX.write_vre_stor_capacity\nGenX.write_vre_stor_charge\nGenX.write_vre_stor_discharge","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor","page":"Outputs Functions","title":"GenX.write_vre_stor","text":"write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage specific files.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor_capacity","page":"Outputs Functions","title":"GenX.write_vre_stor_capacity","text":"write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage capacities.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor_charge","page":"Outputs Functions","title":"GenX.write_vre_stor_charge","text":"write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage charging decision variables/expressions.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_vre_stor_discharge","page":"Outputs Functions","title":"GenX.write_vre_stor_discharge","text":"write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage discharging decision variables/expressions.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Multi-stage-files","page":"Outputs Functions","title":"Write Multi-stage files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_multi_stage_costs\nGenX.write_multi_stage_stats\nGenX.write_multi_stage_settings\nGenX.write_multi_stage_network_expansion\nGenX.write_multi_stage_capacities_charge\nGenX.write_multi_stage_capacities_energy","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_costs","page":"Outputs Functions","title":"GenX.write_multi_stage_costs","text":"write_multi_stage_costs(outpath::String, settings_d::Dict)\n\nThis function writes the file costs_multi_stage.csv to the Results directory. This file contains variable, fixed, startup, network expansion, unmet reserve, and non-served energy costs discounted to year zero.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_stats","page":"Outputs Functions","title":"GenX.write_multi_stage_stats","text":"writemultistagestats(outpath::String, statsd::Dict)\n\nThis function writes the file stats_multi_stage.csv. to the Results directory. This file contains the runtime, upper bound, lower bound, and relative optimality gap for each iteration of the DDP algorithm.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_settings","page":"Outputs Functions","title":"GenX.write_multi_stage_settings","text":"write_multi_stage_settings(outpath::AbstractString, settings_d::Dict)\n\nFunction for writing the multi-stage settings file to the output path for future reference.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_network_expansion","page":"Outputs Functions","title":"GenX.write_multi_stage_network_expansion","text":"write_multi_stage_network_expansion(outpath::String, settings_d::Dict)\n\nThis function writes the file network_expansion_multi_stage.csv to the Results directory. This file contains new transmission capacities for each modeled transmission line for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_capacities_charge","page":"Outputs Functions","title":"GenX.write_multi_stage_capacities_charge","text":"write_multi_stage_capacities_charge(outpath::String, settings_d::Dict)\n\nThis function writes the file capacities_charge_multi_stage.csv to the Results directory. This file contains starting resource charge capacities from the first model stage and end resource charge capacities for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#GenX.write_multi_stage_capacities_energy","page":"Outputs Functions","title":"GenX.write_multi_stage_capacities_energy","text":"write_multi_stage_capacities_energy(outpath::String, settings_d::Dict)\n\nThis function writes the file capacities_energy_multi_stage.csv to the Results directory. This file contains starting resource energy capacities from the first model stage and end resource energy capacities for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-maintenance-files","page":"Outputs Functions","title":"Write maintenance files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_maintenance.jl\"]","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_maintenance-Tuple{AbstractString, Dict, JuMP.Model}","page":"Outputs Functions","title":"GenX.write_maintenance","text":"write_maintenance(path::AbstractString, inputs::Dict, EP::Model)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/write_outputs/#Write-DCOPF-files","page":"Outputs Functions","title":"Write DCOPF files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"GenX.write_angles","category":"page"},{"location":"Model_Reference/write_outputs/#GenX.write_angles","page":"Outputs Functions","title":"GenX.write_angles","text":"write_angles(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting the bus angles for each model zone and time step if the DC_OPF flag is activated\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/write_outputs/#Write-Settings-files","page":"Outputs Functions","title":"Write Settings files","text":"","category":"section"},{"location":"Model_Reference/write_outputs/","page":"Outputs Functions","title":"Outputs Functions","text":"Modules = [GenX]\nPages = [\"write_settings.jl\"]","category":"page"},{"location":"Getting_Started/examples_casestudies/#Running-GenX","page":"Running GenX","title":"Running GenX","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"This section describes how to run GenX with the examples provided in the repository and with user-defined cases. To have a deeper understanding of how to structure the input files and the settings, please refer to the User Guide.","category":"page"},{"location":"Getting_Started/examples_casestudies/#Example-cases","page":"Running GenX","title":"Example cases","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"GenX repository contains several examples to get you started with GenX. These examples are located in the example_systems folder of the repository and are designed to be easy to run and to demonstrate the main features of GenX. ","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The available examples are:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"1_three_zones\n2_three_zones_w_electrolyzer\n3_three_zone_w_co2_capture\n4_three_zones_w_policies_slack\n5_three_zones_w_piecewise_fuel\n6_three_zones_w_multistage\n7_three_zones_w_colocated_VRE_storage\nIEEE_9_bus_DC_OPF","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"note: Note\nThe following instructions assume that you have already installed GenX and its dependencies. If you haven't, please follow the instructions in the Installation Guide.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"To run an example, follow these steps:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"Open a terminal and run Julia with an environment containing GenX;\nRun the Run.jl file located in the example folder.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"For example, to run the 1_three_zones example, you can use the following commands:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"$ julia\njulia> \n(@v1.9) pkg> activate /path/to/env\njulia> using GenX\njulia> include(\"/path/to/GenX/example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"where /path/to/env is the path to the environment containing GenX and /path/to/GenX is the path to the GenX repository containing the examples.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The Run.jl file will read the .csv input files which define the system, the resources, and the policies, will solve the model, and finally will write the results in a results folder located in the same directory as Run.jl.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"tip: Tip\nYou could also run the example from the terminal using the following command:$ julia --project=/path/to/env /path/to/GenX/example_systems/1_three_zones/Run.jl`This is equivalent to open a Julia REPL and call the Run.jl file using the include function. The first option is recommended if you want to run GenX multiple times with different settings because it avoids the overhead of recompiling the code every time you run it.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"note: Note\nThe default solver for GenX is HiGHS.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"For more information on what happens when you run a GenX case, see the Running GenX section.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"note: Note\nThe first seven examples are based on a one-year example with hourly resolution, containing zones representing Massachusetts, Connecticut, and Maine. The ten represented resources include natural gas, solar PV, wind, and lithium-ion battery storage.","category":"page"},{"location":"Getting_Started/examples_casestudies/#Running-GenX-with-user-defined-cases","page":"Running GenX","title":"Running GenX with user-defined cases","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"To run GenX with a user-defined case, you need to create a folder MyCase with the following structure:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"MyCase\n├── settings/\n├── system/\n├── policies/\n├── resources/\n├── README.md\n└── Run.jl","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"where the settings folder contains the configuration files for the model and the solver, the system folder contains the .csv input files related to the system under study, the resource folder contains the .csv input files with the list of generators to include in the model, and the policies folder contains the .csv input files which define the policies to be included in the model. For instance, one case could have the following structure:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"MyCase\n│ \n├── settings\n│ ├── genx_settings.yml # GenX settings\n│ ├── [solver_name]_settings.yml # Solver settings\n│ ├── multi_stage_settings.yml # Multi-stage settings\n│ └── time_domain_reduction.yml # Time-domain clustering settings\n│ \n├── system\n│ ├── Demand_data.csv\n│ ├── Fuel_data.csv\n│ ├── Generators_variability.csv\n│ └── Network.csv\n│ \n├── policies\n│ ├── CO2_cap.csv\n│ ├── Minimum_capacity_requirement.csv\n│ └── Energy_share_requirement.csv\n│ \n├── resources\n│ ├── Thermal.csv\n│ ├── Storage.csv\n│ ├── Vre.csv\n│ ├── Hydro.csv\n│ └── policy_assignments\n| ├── Resource_minimum_capacity_requirement.csv\n│ └── Resource_energy_share_requirement.csv\n│\n└── Run.jl","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"In this example, MyCase will define a case with Themal, Storage, Vre, and Hydro resources, the system folder will provide the data for the demand, fuel, generators' variability, and network, the policies folder will include a CO2 cap, a minimum capacity requirement, and an energy share requirement, and the settings folder will contain the configuration files for the model. ","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The Run.jl file should contain the following code:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"using GenX\n\nrun_genx_case!(dirname(@__FILE__))","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"which will run the case using the default solver. To use a different solver, you can pass the Optimizer object as an argument to run_genx_case! function. For example, to use Gurobi as the solver, you can use the following code:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"using GenX\nusing Gurobi\n\nrun_genx_case!(dirname(@__FILE__), Gurobi.Optimizer)","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"To run the case, open a terminal and run the following command:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"$ julia --project=\"/path/to/env\"\njulia> include(\"/path/to/MyCase/Run.jl\")","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"where /path/to/env is the path to the environment with GenX installed, and /path/to/MyCase is the path to the folder of the MyCase case. Alternatively, you can run the case directly from the terminal using the following command:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"$ julia --project=\"/path/to/env\" /path/to/MyCase/Run.jl","category":"page"},{"location":"Getting_Started/examples_casestudies/#What-happens-when-you-run-a-case","page":"Running GenX","title":"What happens when you run a case","text":"","category":"section"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"Added in 0.3.4","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The entry point for running a GenX case is the run_genx_case!(\"path/to/case\") function, where path/to/case is the path to the case directory that contains the .csv files with the inputs for GenX and the settings folder with the configuration files.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"The following are the main steps performed in this function:","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"Establish path to environment setup files and GenX source files.\nRead in model settings genx_settings.yml from the example directory.\nConfigure solver settings.\nLoad the model inputs from the example directory and perform time-domain clustering if required.\nGenerate a GenX model instance.\nSolve the model.\nWrite the output files to a specified directory.","category":"page"},{"location":"Getting_Started/examples_casestudies/","page":"Running GenX","title":"Running GenX","text":"After the script runs to completion, results will be written to a folder called results, located in the current working directory.","category":"page"},{"location":"installation/#Installation-Guide","page":"Installation Guide","title":"Installation Guide","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"This guide will walk you through the steps to install Julia, the GenX package, and the required dependencies to run GenX.","category":"page"},{"location":"installation/#Installing-Julia","page":"Installation Guide","title":"Installing Julia","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"GenX currently exists in version 0.4.0 and runs only on Julia v1.6.x, 1.7.x, 1.8.x, and 1.9.x, where x>=0 and a minimum version of JuMP v1.1.1. To install Julia, please follow the instructions on the Julia website.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"note: Note\nWe recommend the users to stick to a particular version of Julia to run GenX. If however, the users decide to switch between versions, it's very important to delete the old Manifest.toml file and do a fresh build of GenX.","category":"page"},{"location":"installation/#Downloading-GenX-and-installing-dependencies","page":"Installation Guide","title":"Downloading GenX and installing dependencies","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"After installing Julia, you can download GenX by either cloning the repository or downloading the zip file from the GenX GitHub page. For this tutorial it will be assumed to be within your home directory: /home/youruser/GenX. Once you have downloaded GenX, you can install the dependencies by following the steps below:","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"1. Start a terminal and navigate into the GenX folder.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"2. Type julia --project=. to start an instance of the julia kernel with the project set to the current folder. The flag --project=. indicates that Julia will activate the project environment using the Project.toml present in the current folder, .. If running on Windows, the location of Julia can also be specified as e.g., C:\\julia-1.6.0\\bin\\julia.exe --project=..","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"tip: Tip\nThe file Project.toml in the parent directory lists all of the dependencies and their versions needed to run GenX. You can see all of the packages installed in your Julia environment and their version numbers by running pkg> status or pkg> st on the package manager command line in the Jula REPL (for more information on the Julia package manager, read the documentation for the Pkg.jl or for the Julia standard library).","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"tip: Tip\njulia --project is a shortcut for julia --project=.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"3. Type ] to bring up the package system (GenX) pkg > prompt. This indicates that the GenX project was detected. ","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"warning: Warning\nIf you see (@v1.6) pkg> as the prompt, then the project was not successfully set.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"4. Type instantiate from the (GenX) pkg prompt.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"note: Note for Windows users\nOn Windows there is an issue with the prepopulated MUMPS_seq_jll v5.5.1 that prevents compilation of the solvers. To avoid this issue type add MUMPS_seq_jll@5.4.1 after running instantiate.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"5. Type st to check that the dependecies have been installed. If there is no error, it has been successful.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"tip: Tip\nType the back key to come back to the julia> prompt from the package manager.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"The above steps are shown in Figure 1 and Figure 2.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"(Image: Creating the Julia environment and installing dependencies: Steps 2-4) Figure 1. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"(Image: Creating the Julia environment and installing dependencies: Step 5) Figure 2. Creating the Julia environment and installing dependencies from Project.toml file from inside the GenX folder: Step 5","category":"page"},{"location":"installation/#Installing-solvers","page":"Installation Guide","title":"Installing solvers","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"GenX requires a solver to be installed to solve the optimization problem. By default, GenX uses one of the following open-source freely available solvers:","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"HiGHS for linear programming and MILP (default solver)\nClp for linear programming (LP) problems\nCbc for mixed integer linear programming (MILP) problems","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"We also provide the option to use one of these two commercial solvers: ","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"Gurobi\nCPLEX.","category":"page"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"note: Note on commercial solvers\nUsing Gurobi and CPLEX requires a valid license on the host machine.","category":"page"},{"location":"installation/#Notes-on-previous-versions-of-GenX","page":"Installation Guide","title":"Notes on previous versions of GenX","text":"","category":"section"},{"location":"installation/","page":"Installation Guide","title":"Installation Guide","text":"For those users who has previously cloned GenX, and has been running it successfully so far, and therefore might be unwilling to run it on the latest version of Julia: please look into the GitHub branch, old_version.","category":"page"},{"location":"Model_Reference/Resources/resource/#Resource-types-and-function-interfaces","page":"Resource types","title":"Resource types and function interfaces","text":"","category":"section"},{"location":"Model_Reference/Resources/resource/","page":"Resource types","title":"Resource types","text":"GenX.AbstractResource","category":"page"},{"location":"Model_Reference/Resources/resource/#GenX.AbstractResource","page":"Resource types","title":"GenX.AbstractResource","text":"An abstract type that should be subtyped for users creating GenX resources.\n\n\n\n\n\n","category":"type"},{"location":"Model_Reference/Resources/resource/","page":"Resource types","title":"Resource types","text":"Modules = [GenX]\nPages = [\"resources.jl\"]","category":"page"},{"location":"Model_Reference/Resources/resource/#GenX.default_zero","page":"Resource types","title":"GenX.default_zero","text":"const default_zero = 0\n\nDefault value for resource attributes.\n\n\n\n\n\n","category":"constant"},{"location":"Model_Reference/Resources/resource/#GenX.resource_types","page":"Resource types","title":"GenX.resource_types","text":"resource_types\n\nName of the type of resources available in the model.\n\nPossible values:\n\n:Thermal\n:Vre\n:Hydro\n:Storage\n:MustRun\n:FlexDemand\n:VreStorage\n:Electrolyzer\n\n\n\n\n\n","category":"constant"},{"location":"Model_Reference/Resources/resource/#Base.findall-Tuple{Function, Vector{<:GenX.AbstractResource}}","page":"Resource types","title":"Base.findall","text":"findall(f::Function, rs::Vector{<:AbstractResource})\n\nFind all resources in the vector rs that satisfy the condition given by the function f. Return the resource id instead of the vector index.\n\nArguments\n\nf::Function: The condition function.\nrs::Vector{<:AbstractResource}: The vector of resources.\n\nReturns\n\nVector: The vector of resource ids.\n\nExamples\n\njulia> findall(r -> max_cap_mwh(r) != 0, gen.Storage)\n3-element Vector{Int64}:\n 48\n 49\n 50\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.get-Tuple{GenX.AbstractResource, Symbol, Any}","page":"Resource types","title":"Base.get","text":"Base.get(r::AbstractResource, sym::Symbol, default)\n\nRetrieves the value of a specific attribute from an AbstractResource object. If the attribute exists, its value is returned; otherwise, the default value is returned.\n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\ndefault: The default value to return if the attribute does not exist.\n\nReturns:\n\nThe value of the attribute if it exists in the parent object, default otherwise.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.getproperty-Tuple{GenX.AbstractResource, Symbol}","page":"Resource types","title":"Base.getproperty","text":"Base.getproperty(r::AbstractResource, sym::Symbol)\n\nAllows to access the attributes of an AbstractResource object using dot syntax. It checks if the attribute exists in the object and returns its value, otherwise it throws an ErrorException indicating that the attribute does not exist.\n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\n\nReturns:\n\nThe value of the attribute if it exists in the parent object.\n\nThrows:\n\nErrorException: If the attribute does not exist in the resource.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.getproperty-Tuple{Vector{<:GenX.AbstractResource}, Symbol}","page":"Resource types","title":"Base.getproperty","text":"Base.getproperty(rs::Vector{<:AbstractResource}, sym::Symbol)\n\nAllows to access attributes of a vector of AbstractResource objects using dot syntax. If the sym is an element of the resource_types constant, it returns all resources of that type. Otherwise, it returns the value of the attribute for each resource in the vector.\n\nArguments:\n\nrs::Vector{<:AbstractResource}: The vector of AbstractResource objects.\nsym::Symbol: The symbol representing the attribute name or a type from resource_types.\n\nReturns:\n\nIf sym is an element of the resource_types constant, it returns a vector containing all resources of that type.\nIf sym is an attribute name, it returns a vector containing the value of the attribute for each resource.\n\nExamples\n\njulia> vre_gen = gen.Vre; # gen vector of resources\njulia> typeof(vre_gen)\nVector{Vre} (alias for Array{Vre, 1})\njulia> vre_gen.zone\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.haskey-Tuple{GenX.AbstractResource, Symbol}","page":"Resource types","title":"Base.haskey","text":"haskey(r::AbstractResource, sym::Symbol)\n\nCheck if an AbstractResource object has a specific attribute. It returns a boolean value indicating whether the attribute exists in the parent object.\n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\n\nReturns:\n\ntrue if the attribute exists in the parent object, false otherwise.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.pairs-Tuple{GenX.AbstractResource}","page":"Resource types","title":"Base.pairs","text":"pairs(r::AbstractResource)\n\nReturn an iterator of key-value pairs with the attributes of a given resource.\n\nArguments\n\nr::AbstractResource: The resource.\n\nReturns\n\nPairs: An iterator of key-value pairs over the attributes.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.setindex!-Tuple{Vector{<:GenX.AbstractResource}, Vector, Symbol}","page":"Resource types","title":"Base.setindex!","text":"Base.setindex!(rs::Vector{<:AbstractResource}, value::Vector, sym::Symbol)\n\nDefine dot syntax for setting the attributes specified by sym to the corresponding values in value for a vector of resources.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nvalue::Vector: The vector of values to set for the attribute.\nsym::Symbol: The symbol representing the attribute to set.\n\nReturns\n\nrs::Vector{<:AbstractResource}: The updated vector of resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.setproperty!-Tuple{GenX.AbstractResource, Symbol, Any}","page":"Resource types","title":"Base.setproperty!","text":"setproperty!(r::AbstractResource, sym::Symbol, value)\n\nAllows to set the attribute sym of an AbstractResource object using dot syntax. \n\nArguments:\n\nr::AbstractResource: The resource object.\nsym::Symbol: The symbol representing the attribute name.\nvalue: The value to set for the attribute.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.setproperty!-Tuple{Vector{<:GenX.AbstractResource}, Symbol, Vector}","page":"Resource types","title":"Base.setproperty!","text":"Base.setproperty!(rs::Vector{<:AbstractResource}, sym::Symbol, value::Vector)\n\nSet the attributes specified by sym to the corresponding values in value for a vector of resources.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nsym::Symbol: The symbol representing the attribute to set.\nvalue::Vector: The vector of values to set for the attribute.\n\nReturns\n\nrs::Vector{<:AbstractResource}: The updated vector of resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#Base.show-Tuple{IO, GenX.AbstractResource}","page":"Resource types","title":"Base.show","text":"show(io::IO, r::AbstractResource)\n\nPrint the attributes of the given resource.\n\nArguments\n\nio::IO: The IO stream to print to.\nr::AbstractResource: The resource.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.attributes-Tuple{GenX.AbstractResource}","page":"Resource types","title":"GenX.attributes","text":"attributes(r::AbstractResource)\n\nReturns a tuple of the attribute names of the given resource.\n\nArguments\n\nr::AbstractResource: The resource.\n\nReturns\n\nTuple: A tuple with symbols representing the attribute names.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.electrolyzer-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.electrolyzer","text":"electrolyzer(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all electrolyzer resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.flex_demand-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.flex_demand","text":"flex_demand(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all flexible demand resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.has_all_options_contributing-Union{Tuple{T}, Tuple{GenX.AbstractResource, Vector{T}}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.has_all_options_contributing","text":"has_all_options_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource\n\nCheck if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res contribute to min retirement.\n\nArguments\n\nretrofit_res::AbstractResource: The retrofit resource.\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nBool: True if all retrofit options contribute to min retirement, otherwise false.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.has_all_options_not_contributing-Union{Tuple{T}, Tuple{GenX.AbstractResource, Vector{T}}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.has_all_options_not_contributing","text":"has_all_options_not_contributing(retrofit_res::AbstractResource, rs::Vector{T}) where T <: AbstractResource\n\nCheck if all retrofit options in the retrofit cluster of the retrofit resource retrofit_res do not contribute to min retirement.\n\nArguments\n\nretrofit_res::AbstractResource: The retrofit resource.\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nBool: True if all retrofit options do not contribute to min retirement, otherwise false.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.hydro-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.hydro","text":"hydro(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all hydro resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with-Union{Tuple{T}, Tuple{Vector{T}, Function}, Tuple{Vector{T}, Function, Any}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with","text":"ids_with(rs::Vector{T}, f::Function, default=default_zero) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by f is not equal to default.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The getter of the attribute.\ndefault: The default value of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with attribute not equal to default.\n\nExamples\n\njulia> ids_with(gen.Thermal, existing_cap_mw)\n4-element Vector{Int64}:\n 21\n 22\n 23\n 24\njulia> existing_cap_mw(gen[21])\n7.0773\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with-Union{Tuple{T}, Tuple{Vector{T}, Symbol}, Tuple{Vector{T}, Symbol, Any}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with","text":"ids_with(rs::Vector{T}, name::Symbol, default=default_zero) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by name is not equal to the default value of the attribute.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the attribute.\ndefault: The default value of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with attribute not equal to default.\n\nExamples\n\njulia> ids_with(gen.Thermal, :existing_cap_mw)\n4-element Vector{Int64}:\n 21\n 22\n 23\n 24\njulia> existing_cap_mw(gen[21])\n7.0773\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_all_options_contributing-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_all_options_contributing","text":"ids_with_all_options_contributing(rs::Vector{T}) where T <: AbstractResource\n\nFind the resource ids of the retrofit units in the vector rs where all retrofit options contribute to min retirement.\n\nArguments\n\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nVector{Int64}: The vector of resource ids.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_all_options_not_contributing-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_all_options_not_contributing","text":"ids_with_all_options_not_contributing(rs::Vector{T}) where T <: AbstractResource\n\nFind the resource ids of the retrofit units in the vector rs where all retrofit options do not contribute to min retirement.\n\nArguments\n\nrs::Vector{T}: The vector of resources.\n\nReturns\n\nVector{Int64}: The vector of resource ids.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_nonneg-Union{Tuple{T}, Tuple{Vector{T}, Function}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_nonneg","text":"ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by f is non-negative.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The getter of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with non-negative attribute.\n\nExamples\n\njulia> ids_with_nonneg(gen, max_cap_mw)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_nonneg-Union{Tuple{T}, Tuple{Vector{T}, Symbol}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_nonneg","text":"ids_with_nonneg(rs::Vector{T}, f::Function) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the attribute specified by name is non-negative.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with non-negative attribute.\n\nExamples\n\njulia> ids_with_nonneg(gen, max_cap_mw)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_policy-Union{Tuple{T}, Tuple{Vector{T}, Function}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_policy","text":"ids_with_policy(rs::Vector{T}, f::Function; tag::Int64) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the policy specified by f with tag equal to tag is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The policy getter function.\ntag::Int64: The tag of the policy.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with a positive value for policy f and tag tag.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_policy-Union{Tuple{T}, Tuple{Vector{T}, Symbol}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_policy","text":"idswithpolicy(rs::Vector{T}, name::Symbol; tag::Int64) where T <: AbstractResource\n\nFunction for finding resources in a vector rs where the policy specified by name with tag equal to tag is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the policy.\ntag::Int64: The tag of the policy.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with a positive value for policy name and tag tag.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_positive-Union{Tuple{T}, Tuple{Vector{T}, Function}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_positive","text":"ids_with_positive(rs::Vector{T}, f::Function) where T <: AbstractResource\n\nFunction for finding indices of resources in a vector rs where the attribute specified by f is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nf::Function: The getter of the attribute.\n\nReturns\n\nids (Vector{Int64}): The vector of resource ids with positive attribute.\n\nExamples\n\njulia> ids_with_positive(gen, max_cap_mw)\n3-element Vector{Int64}:\n 3 \n 4\n 5\njulia> max_cap_mw(gen[3])\n4.888236\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.ids_with_positive-Union{Tuple{T}, Tuple{Vector{T}, Symbol}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.ids_with_positive","text":"ids_with_positive(rs::Vector{T}, name::Symbol) where T <: AbstractResource\n\nFunction for finding indices of resources in a vector rs where the attribute specified by name is positive.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\nname::Symbol: The name of the attribute.\n\nReturns\n\nVector{Int64}: The vector of resource ids with positive attribute.\n\nExamples\n\njulia> ids_with_positive(gen, :max_cap_mw)\n3-element Vector{Int64}:\n 3 \n 4\n 5\njulia> max_cap_mw(gen[3])\n4.888236\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.must_run-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.must_run","text":"must_run(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all must-run resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.resource_by_name-Tuple{Vector{<:GenX.AbstractResource}, AbstractString}","page":"Resource types","title":"GenX.resource_by_name","text":"resource_by_name(rs::Vector{<:AbstractResource}, name::AbstractString)\n\nFind the resource with name in the vector rs.\n\nArguments\n\nrs: A vector of resources.\nname: The name of the resource.\n\nReturns\n\nAbstractResource: The resource with the name name.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.resources_in_retrofit_cluster_by_rid-Tuple{Vector{<:GenX.AbstractResource}, String}","page":"Resource types","title":"GenX.resources_in_retrofit_cluster_by_rid","text":"resources_in_retrofit_cluster_by_rid(rs::Vector{<:AbstractResource}, cluster_id::String)\n\nFind RID's of resources with retrofit cluster id `clusterid`.\n\nArguments\n\nrs::Vector{<:AbstractResource}: The vector of resources.\ncluster_id::String: The retrofit cluster id.\n\nReturns\n\nVector{Int64}: The vector of resource ids in the retrofit cluster.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.resources_in_zone_by_rid-Tuple{Vector{<:GenX.AbstractResource}, Int64}","page":"Resource types","title":"GenX.resources_in_zone_by_rid","text":"resources_in_zone_by_rid(rs::Vector{<:AbstractResource}, zone::Int)\n\nFind R_ID's of resources in a zone.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.solar-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.solar","text":"solar(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located solar resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage","text":"storage(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all storage resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_ac_charge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_ac_charge","text":"storage_ac_charge(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located storage resources in the vector rs that charge AC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_ac_discharge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_ac_discharge","text":"storage_ac_discharge(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located storage resources in the vector rs that discharge AC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_dc_charge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_dc_charge","text":"storage_dc_charge(rs::Vector{T}) where T <: AbstractResource\nReturns the indices of all co-located storage resources in the vector `rs` that charge DC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.storage_dc_discharge-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.storage_dc_discharge","text":"storage_dc_discharge(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located storage resources in the vector rs that discharge DC.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.thermal-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.thermal","text":"thermal(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all thermal resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.validate_boolean_attribute-Tuple{GenX.AbstractResource, Symbol}","page":"Resource types","title":"GenX.validate_boolean_attribute","text":"validate_boolean_attribute(r::AbstractResource, attr::Symbol)\n\nValidate that the attribute attr in the resource r is boolean {0, 1}.\n\nArguments\n\nr::AbstractResource: The resource.\nattr::Symbol: The name of the attribute.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.vre-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.vre","text":"vre(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all Vre resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.vre_stor-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.vre_stor","text":"vre_stor(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all VRE_STOR resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.wind-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Resource types","title":"GenX.wind","text":"wind(rs::Vector{T}) where T <: AbstractResource\n\nReturns the indices of all co-located wind resources in the vector rs.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/resource/#GenX.@interface","page":"Resource types","title":"GenX.@interface","text":"interface(name, default=default_zero, type=AbstractResource)\n\nDefine a function interface for accessing the attribute specified by name in a resource of type type.\n\nArguments\n\nname: The name of the attribute.\ndefault: The default value to return if the attribute is not found.\ntype: The type of the resource.\n\nReturns\n\nFunction: The generated function.\n\nExamples\n\njulia> @interface max_cap_mw 0 Vre\njulia> max_cap_mw(gen.Vre[3])\n4.888236\njulia> max_cap_mw.(gen.Vre) # vectorized\n5-element Vector{Float64}:\n 0.0\n 0.0\n 4.888236\n 20.835569\n 9.848441999999999\n\n\n\n\n\n","category":"macro"},{"location":"Model_Reference/Resources/hydro_inter_period_linkage/#Reservoir-Hydro","page":"Long Duration Hydro","title":"Reservoir Hydro","text":"","category":"section"},{"location":"Model_Reference/Resources/hydro_inter_period_linkage/","page":"Long Duration Hydro","title":"Long Duration Hydro","text":"Modules = [GenX]\nPages = [\"hydro_inter_period_linkage.jl\"]","category":"page"},{"location":"Model_Reference/Resources/hydro_inter_period_linkage/#GenX.hydro_inter_period_linkage!-Tuple{JuMP.Model, Dict}","page":"Long Duration Hydro","title":"GenX.hydro_inter_period_linkage!","text":"hydro_inter_period_linkage!(EP::Model, inputs::Dict)\n\nThis function creates variables and constraints enabling modeling of long duration storage resources when modeling representative time periods.\n\nStorage inventory balance at beginning of each representative period The constraints in this section are used to approximate the behavior of long-duration energy storage technologies when approximating annual grid operations by modeling operations over representative periods. Previously, the state of charge balance for storage (as defined in storage_all()) assumed that state of charge at the beginning and end of each representative period has to be the same. In other words, the amount of energy built up or consumed by storage technology o in zone z over the representative period m, Delta Q_ozm = 0. This assumption implicitly excludes the possibility of transferring energy from one representative period to the other which could be cost-optimal when the capital cost of energy storage capacity is relatively small. To model long-duration energy storage using representative periods, we replace the state of charge equation, such that the first term on the right hand side accounts for change in storage inventory associated with representative period m (Delta Q_ozm), which could be positive (net accumulation) or negative (net reduction).\n\nbeginaligned\n Gamma_oz(m-1)times tau^period+1 =left(1-eta_oz^lossright)times left(Gamma_ozmtimes tau^period -Delta Q_ozmright) - \n frac1eta_oz^dischargeTheta_oz(m-1)times tau^period+1 + eta_oz^chargePi_oz(m-1)times tau^period+1 quad forall o in mathcalO^LDES z in mathcalZ m in mathcalM\nendaligned\n\nBy definition mathcalT^start=left(m-1right) times tau^period+1 m in mathcalM, which implies that this constraint is defined for all values of t in T^start.\n\nStorage inventory change input periods We need additional variables and constraints to approximate energy exchange between representative periods, while accounting for their chronological occurence in the original input time series data and the possibility that two representative periods may not be adjacent to each other (see Figure below). To implement this, we introduce a new variable Q_oz n that models inventory of storage technology o in O in zone z in each input period n in mathcalN. Additionally we define a function mapping, f n rightarrow m, that uniquely maps each input period n to its corresponding representative period m. This mapping is available as an output of the process used to identify representative periods (E.g. k-means clustering Mallapragada et al., 2018). (Image: Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations) Figure. Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations The following two equations define the storage inventory at the beginning of each input period n+1 as the sum of storage inventory at begining of previous input period n plus change in storage inventory for that period. The latter is approximated by the change in storage inventory in the corresponding representative period, identified per the mapping f(n). The second constraint relates the storage level of the last input period, N, with the storage level at the beginning of the first input period. Finally, if the input period is also a representative period, then a third constraint enforces that initial storage level estimated by the intra-period storage balance constraint should equal the initial storage level estimated from the inter-period storage balance constraints. Note that N refers to the last modeled period.\n\nbeginaligned\n Q_ozn+1 = Q_ozn + Delta Q_ozf(n)\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalNsetminusN\nendaligned\n\nbeginaligned\n Q_oz1 = Q_ozN + Delta Q_ozf(N)\nquad forall o in mathcalO^LDES z in mathcalZ n = N\nendaligned\n\nbeginaligned\n Q_ozn =Gamma_ozf(n)times tau^period - Delta Q_ozm\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalN^rep\nendaligned\n\nFinally, the next constraint enforces that the initial storage level for each input period n must be less than the installed energy capacity limit. This constraint ensures that installed energy storage capacity is consistent with the state of charge during both the operational time periods t during each sample period m as well as at the start of each chronologically ordered input period n in the full annual time series.\n\nbeginaligned\n Q_ozn leq Delta^total energy_oz\nquad forall n in mathcalN o in mathcalO^LDES\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/investment_energy/#Investment-Energy","page":"Investment Energy","title":"Investment Energy","text":"","category":"section"},{"location":"Model_Reference/Resources/investment_energy/","page":"Investment Energy","title":"Investment Energy","text":"Modules = [GenX]\nPages = [\"investment_energy.jl\"]","category":"page"},{"location":"Model_Reference/Resources/investment_energy/#GenX.investment_energy!-Tuple{JuMP.Model, Dict, Dict}","page":"Investment Energy","title":"GenX.investment_energy!","text":"investment_energy!(EP::Model, inputs::Dict)\n\nThis function defines the expressions and constraints keeping track of total available storage charge capacity across all resources as well as constraints on capacity retirements. The function also adds investment and fixed O\\&M related costs related to charge capacity to the objective function.\n\nThe total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity.\n\nbeginaligned\n Delta^totalenergy_yz =(overlineDelta^energy_yz+Omega^energy_yz-Delta^energy_yz) forall y in mathcalO z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity.\n\nbeginaligned\nDelta^energy_yz leq overlineDelta^energy_yz\n\t\thspace4 cm forall y in mathcalO z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^energy and underlineOmega_yz^energy is defined, then we impose constraints on minimum and maximum power capacity.\n\nbeginaligned\n Delta^totalenergy_yz leq overlineOmega^energy_yz\n\thspace4 cm forall y in mathcalO z in mathcalZ \n Delta^totalenergy_yz geq underlineOmega^energy_yz\n\thspace4 cm forall y in mathcalO z in mathcalZ\nendaligned\n\nIn addition, this function adds investment and fixed O\\&M related costs related to charge capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalO sum_z in mathcalZ\n\tleft( (pi^INVESTenergy_yz times Omega^energy_yz)\n\t+ (pi^FOMenergy_yz times Delta^totalenergy_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"User_Guide/slack_variables_overview/#Policy-Slack-Variables","page":"Slack Variables for Policies","title":"Policy Slack Variables","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Added in 0.3.5","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Rather than modeling policy requirements as inflexible constraints, it may be advantageous to instead allow these requirements to be violated at some predetermined cost. This is accomplished via 'slack variables,' which can be used by the model to meet a policy constraint if it cannot be met cost-effectively by normal means. Once the incremental shadow price of meeting a policy constraint rises above a cost threshold set by the user, the model will rely on the slack variable to fill any remaining gap. ","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Using slack variables rather than hard constraints may be useful for GenX users who wish to avoid unexpected infeasibilities resulting from policy requirements that cannot be met. Using slack variables with very high cost thresholds, users can quickly identify specific policy constraints that are effectively infeasible without causing errors. ","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables with lower assigned costs can also be used to model policies with built-in cost thresholds, for example a CO2 Cap with a maximum allowable carbon price of $200/ton. They can be activated for each individual policy type available in GenX, including: Capacity Reserve Margins, Energy Share Requirements, CO2 Caps, Minimum Capacity Requirements, and Maximum Capacity Requirements. ","category":"page"},{"location":"User_Guide/slack_variables_overview/#Running-cases-with-slack-variables","page":"Slack Variables for Policies","title":"Running cases with slack variables","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables are turned off by default in GenX, but can be automatically activated for each policy type by providing the relevant inputs. Slack variables will only be activated when the relevant policy type is itself activated in GenX_settings.yml. For some policy types, slack variables are activated by providing a new input file, while for others they are activated by modifying an existing file. Instructions for each policy type are listed below:","category":"page"},{"location":"User_Guide/slack_variables_overview/#Capacity-Reserve-Margin","page":"Slack Variables for Policies","title":"Capacity Reserve Margin","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Capacity Reserve Margin constraints are created when GenX detects the presence of the file Capacity_reserve_margin_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CRMConstraint' naming the individual Capacity Reserve Margin constraints in the same order in which they are listed in the first row of `Capacityreserve_margin.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /MW.","category":"page"},{"location":"User_Guide/slack_variables_overview/#CO2-Cap","page":"Slack Variables for Policies","title":"CO2 Cap","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for CO2 Cap constraints are created when GenX detects the presence of the file CO2_cap_slack.csv in the Inputs folder. This file should contain two columns: one titled 'CO2CapConstraint' naming the individual CO2 Cap constraints in the same order in which they are listed in the first row of CO2_Cap.csv, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are /ton. The CO2 Cap slack variable itself is always in units of tons of CO2, even if the CO2 Cap is a rate-based cap.","category":"page"},{"location":"User_Guide/slack_variables_overview/#Energy-Share-Requirement","page":"Slack Variables for Policies","title":"Energy Share Requirement","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Energy Share Requirement constraints are created when GenX detects the presence of the file Energy_share_requirement_slack.csv in the Inputs folder. This file should contain two columns: one titled 'ESRConstraint' naming the individual Energy Share Requirement constraints in the same order in which they are listed in the first row of `Energyshare_requirement.csv`, and a second titled 'PriceCap' containing the price thresholds for each constraint. The units for these thresholds are $/MWh.","category":"page"},{"location":"User_Guide/slack_variables_overview/#Minimum-Capacity-Requirement","page":"Slack Variables for Policies","title":"Minimum Capacity Requirement","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Minimum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Minimum_capacity_requirement.csv. This column contains the price thresholds for each Minimum Capacity Requirement constraint, in units of $/MW. ","category":"page"},{"location":"User_Guide/slack_variables_overview/#Maximum-Capacity-Requirement","page":"Slack Variables for Policies","title":"Maximum Capacity Requirement","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"Slack variables for Maximum Capacity Requirement constraints are created when GenX detects the presence of a column titled 'PriceCap' in the file Maximum_capacity_requirement.csv. This column contains the price thresholds for each Maximum Capacity Requirement constraint, in units of $/MW. ","category":"page"},{"location":"User_Guide/slack_variables_overview/#Slack-Variables-Results-Files","page":"Slack Variables for Policies","title":"Slack Variables Results Files","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"By default, a policy type's result files include the shadow prices for each policy constraint. When slack variables are activated, outputs also include the final values of the slack variables (i.e. the amount by which the policy constraint was violated), and the total costs associated with those slack variables. These files are named using the convention X_prices_and_penalties.csv, where X is the name of the relevant policy type.","category":"page"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"GenX will also print the total cost associated with each activated slack variable type in the file costs.csv.","category":"page"},{"location":"User_Guide/slack_variables_overview/#Slack-Variables-Example","page":"Slack Variables for Policies","title":"Slack Variables Example","text":"","category":"section"},{"location":"User_Guide/slack_variables_overview/","page":"Slack Variables for Policies","title":"Slack Variables for Policies","text":"The folder Example_Systems/SmallNewEngland/ThreeZones_Slack_Variables_Example contains examples of the input files needed to activate slack variables for each of the policy types in GenX. Running this example with a given set of policy constraints activated will generate the relevant slack variables and print their outputs.","category":"page"},{"location":"User_Guide/generate_alternatives/#Running-Modeling-to-Generate-Alternatives-with-GenX","page":"MGA package","title":"Running Modeling to Generate Alternatives with GenX","text":"","category":"section"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"GenX includes a modeling to generate alternatives (MGA) package that can be used to automatically enumerate a diverse set of near cost-optimal solutions to electricity system planning problems. To use the MGA algorithm, user will need to perform the following tasks:","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"Add a Resource_Type column in all the resource .csv files denoting the type of each technology.\nAdd a MGA column in all the resource .csv files denoting the availability of the technology.\nSet the ModelingToGenerateAlternatives flag in the GenX_Settings.yml file to 1.\nSet the ModelingtoGenerateAlternativeSlack flag in the GenX_Settings.yml file to the desirable level of slack.\nCreate a Rand_mga_objective_coefficients.csv file to provide random objective function coefficients for each MGA iteration.","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"For each iteration, number of rows in the Rand_mga_objective_coefficients.csv file represents the number of distinct technology types while number of columns represent the number of model zones.","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"Solve the model using Run.jl file.","category":"page"},{"location":"User_Guide/generate_alternatives/","page":"MGA package","title":"MGA package","text":"Results from the MGA algorithm would be saved in MGAmax and MGAmin folders in the Example_Systems/ folder.","category":"page"},{"location":"User_Guide/TDR_input/#Time-domain-reduction","page":"Time-domain Reduction Inputs","title":"Time-domain reduction","text":"","category":"section"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"Modeling grid operations for each hour of the year can be computationally expensive for models with many zones and resources. Rather than modeling and optimizing power grid operations at a high temporal resolution (e.g., hourly, over a full year) while evaluating new capacity investments, which can be computationally expensive for large-scale studies with several resources, it may be useful to consider a reduced temporal resolution to model annual grid operations. Time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. Such a time-domain reduction is often employed in capacity expansion models as a way to balance model spatial and temporal resolution as well as representation of dispatch, while ensuring reasonable computational times. GenX allows the option of performing time-domain reduction on the user supplied time-series input data to produce a representative time series at the desired level of temporal resolution. The time-domain reduction method provided allows the user to automate these features while specifying the various parameters of the time-domain reduction 'clustering' algorithm to be used in formulating the resulting optimization model. The below table summarizes the list of parameters to be specified by the user to perform the time domain reduction implemented in GenX. These parameters are passed to GenX via the YAML file time_domain_reduction_settings.yml.","category":"page"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"It's also possible for GenX perform clustering separately from the optimization task. Check out the Running a case with Time Domain Reduction section for more information. ","category":"page"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"Structure of the time_domain_reduction.yml file","category":"page"},{"location":"User_Guide/TDR_input/","page":"Time-domain Reduction Inputs","title":"Time-domain Reduction Inputs","text":"Key Description\nTimesteps_per_period The number of timesteps (e.g., hours) in each representative period (i.e. 168 for weeks, 24 for days, 72 for three-day periods, etc).\nUseExtremePeriods 1 = Include outliers (by performance or demand/resource extreme) as their own representative extreme periods. This setting automatically includes periods based on criteria outlined in the dictionary ExtremePeriods. Extreme periods can be selected based on following criteria applied to demand profiles or solar and wind capacity factors profiles, at either the zonal or system level. A) absolute (timestep with min/max value) statistic (minimum, maximum) and B) integral (period with min/max summed value) statistic (minimum, maximum). For example, the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select Demand, System, Absolute, and Max.\n 0 = Do not include extreme periods.\nExtremePeriods If UseExtremePeriods = 1, use this dictionary to select which types of extreme periods to use. Select by profile type (Demand, PV, or Wind), geography (Zone or System), grouping by timestep or by period (Absolute or Integral), and statistic (Maximum or Minimum).\nClusterMethod Either kmeans or kmedoids, the method used to cluster periods and determine each time step's representative period.\nScalingMethod Either N or S, the decision to normalize ([0,1]) or standardize (mean 0, variance 1) the input data prior to clustering.\nMinPeriods The minimum number of representative periods used to represent the input data. If using UseExtremePeriods, this must be greater or equal to the number of selected extreme periods. If IterativelyAddPeriods is off, this will be the total number of representative periods.\nMaxPeriods The maximum number of representative periods - both clustered and extreme - that may be used to represent the input data.\nIterativelyAddPeriods 1 = Add representative periods until the error threshold between input data and represented data is met or the maximum number of representative periods is reached.\n 0 = Use only the minimum number of representative periods. This minimum value includes the selected extreme periods if UseExtremePeriods is on.\nThreshold Iterative period addition will end if the period farthest from its representative period (as measured using Euclidean distance) is within this percentage of the total possible error (for normalization) or 95% of the total possible error (± 2 σ for standardization). E.g., for a threshold of 0.01, each period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the maximum is reached).\nIterateMethod Either ‘cluster' (Default) or ‘extreme', whether to increment the number of clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.\nnReps Default = 200, the number of kmeans/kmedoids repetitions at the same setting.\nDemandWeight Default = 1, a multiplier on demand columns to optionally prioritize better fits for demand profiles over resource capacity factor or fuel price profiles.\nWeightTotal Default = 8760, the sum to which the relative weights of representative periods will be scaled.\nClusterFuelPrices Either 1 or 0, whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data.csv in the TimeDomainReductionFolder with reshaped fuel prices based on the number and size of the representative periods but will not use the fuel price time series for selection of representative periods.","category":"page"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#Dual-Dynamic-Programming-Algorithm","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"Dual Dynamic Programming Algorithm","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"Model multi stage: Dual Dynamic Programming Algorithm","text":"Modules = [GenX]\nPages = [\"dual_dynamic_programming.jl\"]","category":"page"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.add_cut-Tuple{JuMP.Model, JuMP.Model, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.add_cut","text":"add_cut(EP_cur::Model, EP_next::Model, start_cap_d::Dict, cap_track_d::Dict)\n\ninputs:\n\nEP_cur - JuMP model from the current model stage p.\nEP_next - JuMP model from the next model stage p+1..\nstart_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\ncap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\n\nreturns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.configure_ddp_dicts-Tuple{Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.configure_ddp_dicts","text":"configure_ddp_dicts(setup::Dict, inputs::Dict)\n\nThis function instantiates Dictionary objects containing the names of linking expressions, constraints, and variables used in multi-stage modeling.\n\ninputs:\n\nsetup - Dictionary object containing GenX settings and key parameters.\ninputs – Dictionary of inputs for each model period, generated by the load_inputs() method.\n\nreturns:\n\nstart_cap_d – Dictionary which contains linking expression names as keys and linking constraint names as values, used for setting the end capacity in stage p to the starting capacity in stage p+1.\ncap_track_d – Dictionary which contains linking variable names as keys and linking constraint names as values, used for enforcing endogenous retirements.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.fix_capacity_tracking-Tuple{JuMP.Model, JuMP.Model, Dict, Int64}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.fix_capacity_tracking","text":"fix_capacity_tracking(EP_prev::Model, EP_cur::Model, cap_track_d::Dict, cur_stage::Int)\n\nThis function sets the right hand side values of the new and retired capacity tracking linking constraints in the current stage p to the realized values of the new and retired capacity tracking linking variables from the previous stage p-1 as part of the forward pass. where tracking linking variables are defined variables for tracking, linking and passing realized expansion and retirement of capacities of each stage to the next stage. Tracking linking variables are each defined in endogenous_retirement_discharge, endogenous_retirement_energy, and endogenous_retirement_charge functions. Three examples are \"vCAPTRACK\", \"vCAPTRACKCHARGE\", and \"\"vCAPTRACKENERGY\"\n\ninputs:\n\nEP_prev - JuMP model from the previous model stage p-1.\nEP_cur - JuMP model from the current model stage p.\ncap_track_d – Dictionary which contains key-value pairs of capacity addition and retirement tracking variable names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\ncur_period – Int representing the current model stage p.\n\nreturns: JuMP model with updated linking constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.fix_initial_investments-Tuple{JuMP.Model, JuMP.Model, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.fix_initial_investments","text":"fix_initial_investments(EP_prev::Model, EP_cur::Model, start_cap_d::Dict)\n\nThis function sets the right hand side values of the existing capacity linking constraints in the current stage p to the realized values of the total available end capacity linking variable expressions from the previous stage p-1 as part of the forward pass.\n\ninputs:\n\nEP_prev - JuMP model from the previous model stage p-1.\nEP_cur - JuMP model from the current model stage p.\nstart_cap_d – Dictionary which contains key-value pairs of available capacity investment expression names (as Symbols) as keys and their corresponding linking constraint names (as Symbols) as values.\n\nreturns: JuMP model with updated linking constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.generate_cut_component_inv-Tuple{JuMP.Model, JuMP.Model, Symbol, Symbol}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.generate_cut_component_inv","text":"generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)\n\nThis function generates Bender's cut expressions for linking capacity investment variable expression in the form:\n\nbeginaligned\n mu_next^top(hatx_cur - x_cur)\nendaligned\n\nwhere mu_next is a vector of dual values of the linking constraints defined by constr_name in EP_next, hatx_cur is a vector of realized values from the forward pass of the linking capacity investment variable expressions expr_name from EP_cur, and x_cur is a vector of unrealized linking capacity investment variable expressions from EP_cur. inputs:\n\ninputs:\n\nEP_cur - JuMP model from the current model stage p, solved in the forward pass.\nEP_next - JuMP model from the next model stage p+1, solved in the forward pass.\nexpr_name – Symbol representing the name of a JuMP expression array which contains linking capacity investment variables.\nconstr_name – Symbol representing the name of the array of linking JuMP constraints which contain the linking capacity investment variables.\n\nreturns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.generate_cut_component_track-Tuple{JuMP.Model, JuMP.Model, Symbol, Symbol}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.generate_cut_component_track","text":"generate_cut_component_inv(EP_cur::Model, EP_next::Model, expr_name::Symbol, constr_name::Symbol)\n\nThis function generates Bender's cut expressions for total new or retired capacity tracking linking variables in the form:\n\nbeginaligned\n mu_next^top(hatx_cur - x_cur)\nendaligned\n\nwhere mu_next is a vector of dual values of the linking constraints defined by constr_name in EP_next, hatx_cur is a vector of realized values from the forward pass of the new or retired capacity tracking linking variables var_name from EP_cur, and x_cur is a vector of unrealized new or retired capacity tracking linking variables from EP_cur.\n\ninputs:\n\nEP_cur - JuMP model from the current model stage p.\nEP_next - JuMP model from the next model stage p+1.\nvar_name – Symbol representing the name of a JuMP variable array which contains total new or retired capacity tracking linking variables.\nconstr_name – Symbol representing the name of the array of linking JuMP constraints which contain total new or retired capacity tracking linking variables.\n\nreturns: JuMP expression representing a sum of Benders cuts for linking capacity investment variables to be added to the cost-to-go function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.initialize_cost_to_go-Tuple{Dict, JuMP.Model, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.initialize_cost_to_go","text":"initialize_cost_to_go(settings_d::Dict, EP::Model)\n\nThis function scales the model objective function so that costs are consistent with multi-stage modeling and introduces a cost-to-go function variable to the objective function.\n\nThe updated objective function OBJ^* returned by this method takes the form:\n\nbeginaligned\n OBJ^* = DF * OPEXMULT * OBJ + alpha\nendaligned\n\nwhere OBJ is the original objective function. OBJ is scaled by two terms. The first is a discount factor (applied only in the non-myopic case), which discounts costs associated with the model stage p to year-0 dollars:\n\nbeginaligned\n DF = frac1(1+WACC)^L*(p-1)\nendaligned\n\nwhere WACC is the weighted average cost of capital, and L is the length of each stage in years (both set in multi_stage_settings.yml)\n\nThe second term is a discounted sum of annual operational expenses incurred each year of a multi-year model stage:\n\nbeginaligned\n OPEXMULT = sum^L_l=1frac1(1+WACC)^l-1\nendaligned\n\nNote that although the objective function contains investment costs, which occur only once and thus do not need to be scaled by OPEXMULT, these costs are multiplied by a factor of frac1WACC before being added to the objective function in investment_discharge_multi_stage(), investment_charge_multi_stage(), investment_energy_multi_stage(), and transmission_multi_stage(). Thus, this step scales these costs back to their correct value.\n\nThe cost-to-go function alpha represents an approximation of future costs given the investment and retirement decisions in the current stage. It is constructed through the addition of cuts to the cost-to-go function alpha during the backwards pass.\n\ninputs:\n\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\nEP – JuMP model.\n\nreturns: JuMP model with updated objective function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.run_ddp-Tuple{Dict, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.run_ddp","text":"run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)\n\nThis function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.\n\ninputs:\n\nmodels_d – Dictionary which contains a JuMP model for each model period.\nsetup - Dictionary object containing GenX settings and key parameters.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.\n\nreturns:\n\nmodels_d – Dictionary which contains a JuMP model for each model stage, modified by this method.\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/dual_dynamic_programming/#GenX.write_multi_stage_outputs-Tuple{Dict, String, Dict, Dict}","page":"Model multi stage: Dual Dynamic Programming Algorithm","title":"GenX.write_multi_stage_outputs","text":"write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)\n\nThis function calls various methods which write multi-stage modeling outputs as .csv files.\n\ninputs:\n\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-the-Solvers","page":"Solver Configurations","title":"Configuring the Solvers","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_solver.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_solver-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_solver","text":"configure_solver(solver_settings_path::String, optimizer::Any)\n\nThis method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\\_model() method.\n\nArguments\n\nsolver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.\noptimizer::Any: the optimizer instance to be configured.\n\nCurrently supported solvers include: \"Gurobi\", \"CPLEX\", \"Clp\", \"Cbc\", or \"SCIP\"\n\nReturns\n\noptimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#GenX.infer_solver-Tuple{Any}","page":"Solver Configurations","title":"GenX.infer_solver","text":"infer_solver(optimizer::Any)\n\nReturn the name (String) of the solver to be used in the GenX.configure_solver method according to the solver imported by the user. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#GenX.rename_keys-Tuple{Dict, Dict}","page":"Solver Configurations","title":"GenX.rename_keys","text":"rename_keys(attributes:Dict, new_key_names::Dict)\n\nRenames the keys of the attributes dictionary based on old->new pairs in the newkeynames dictionary.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-HiGHS","page":"Solver Configurations","title":"Configuring HiGHS","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_highs.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_highs-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_highs","text":"configure_highs(solver_settings_path::String)\n\nReads user-specified solver settings from highs_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes HiGHS optimizer instance to be used in the GenX.generate_model() method.\n\nThe HiGHS optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided: \tAll the references are in https://github.com/jump-dev/HiGHS.jl, https://github.com/ERGO-Code/HiGHS, and https://highs.dev/\n\n# HiGHS Solver Parameters\n# Common solver settings\nFeasib_Tol: 1.0e-06 # Primal feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]\nOptimal_Tol: 1.0e-03 # Dual feasibility tolerance # [type: double, advanced: false, range: [1e-10, inf], default: 1e-07]\nTimeLimit: Inf # Time limit # [type: double, advanced: false, range: [0, inf], default: inf]\nPre_Solve: choose # Presolve option: \"off\", \"choose\" or \"on\" # [type: string, advanced: false, default: \"choose\"]\nMethod: ipm #choose #HiGHS-specific solver settings # Solver option: \"simplex\", \"choose\" or \"ipm\" # [type: string, advanced: false, default: \"choose\"] In order to run a case when the UCommit is set to 1, i.e. MILP instance, set the Method to choose\n\n#HiGHS-specific solver settings\n# Parallel option: \"off\", \"choose\" or \"on\"\n# [type: string, advanced: false, default: \"choose\"]\nparallel: choose\n\n# Compute cost, bound, RHS and basic solution ranging: \"off\" or \"on\"\n# [type: string, advanced: false, default: \"off\"]\nranging: off\n\n# Limit on cost coefficient: values larger than this will be treated as infinite\n# [type: double, advanced: false, range: [1e+15, inf], default: 1e+20]\ninfinite_cost: 1e+20\n\n# Limit on |constraint bound|: values larger than this will be treated as infinite\n# [type: double, advanced: false, range: [1e+15, inf], default: 1e+20]\ninfinite_bound: 1e+20\n\n# Lower limit on |matrix entries|: values smaller than this will be treated as zero\n# [type: double, advanced: false, range: [1e-12, inf], default: 1e-09]\nsmall_matrix_value: 1e-09\n\n# Upper limit on |matrix entries|: values larger than this will be treated as infinite\n# [type: double, advanced: false, range: [1, inf], default: 1e+15]\nlarge_matrix_value: 1e+15\n\n# IPM optimality tolerance\n# [type: double, advanced: false, range: [1e-12, inf], default: 1e-08]\nipm_optimality_tolerance: 1e-08\n\n# Objective bound for termination\n# [type: double, advanced: false, range: [-inf, inf], default: inf]\nobjective_bound: Inf\n\n# Objective target for termination\n# [type: double, advanced: false, range: [-inf, inf], default: -inf]\nobjective_target: -Inf\n\n# random seed used in HiGHS\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 0]\nrandom_seed: 0\n\n# number of threads used by HiGHS (0: automatic)\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 0]\nthreads: 0\n\n# Debugging level in HiGHS\n# [type: HighsInt, advanced: false, range: {0, 3}, default: 0]\nhighs_debug_level: 0\n\n# Analysis level in HiGHS\n# [type: HighsInt, advanced: false, range: {0, 63}, default: 0]\nhighs_analysis_level: 0\n\n# Strategy for simplex solver 0 => Choose; 1 => Dual (serial); 2 => Dual (PAMI); 3 => Dual (SIP); 4 => Primal\n# [type: HighsInt, advanced: false, range: {0, 4}, default: 1]\nsimplex_strategy: 1\n\n# Simplex scaling strategy: off / choose / equilibration / forced equilibration / max value 0 / max value 1 (0/1/2/3/4/5)\n# [type: HighsInt, advanced: false, range: {0, 5}, default: 1]\nsimplex_scale_strategy: 1\n\n# Strategy for simplex crash: off / LTSSF / Bixby (0/1/2)\n# [type: HighsInt, advanced: false, range: {0, 9}, default: 0]\nsimplex_crash_strategy: 0\n\n# Strategy for simplex dual edge weights: Choose / Dantzig / Devex / Steepest Edge (-1/0/1/2)\n# [type: HighsInt, advanced: false, range: {-1, 2}, default: -1]\nsimplex_dual_edge_weight_strategy: -1\n\n# Strategy for simplex primal edge weights: Choose / Dantzig / Devex / Steepest Edge (-1/0/1/2)\n# [type: HighsInt, advanced: false, range: {-1, 2}, default: -1]\nsimplex_primal_edge_weight_strategy: -1\n\n# Iteration limit for simplex solver\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nsimplex_iteration_limit: 2147483647\n\n# Limit on the number of simplex UPDATE operations\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 5000]\nsimplex_update_limit: 5000\n\n# Iteration limit for IPM solver\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nipm_iteration_limit: 2147483647\n\n# Minimum level of concurrency in parallel simplex\n# [type: HighsInt, advanced: false, range: {1, 8}, default: 1]\nsimplex_min_concurrency: 1\n\n# Maximum level of concurrency in parallel simplex\n# [type: HighsInt, advanced: false, range: {1, 8}, default: 8]\nsimplex_max_concurrency: 8\n\n# Enables or disables solver output\n# [type: bool, advanced: false, range: {false, true}, default: true]\noutput_flag: true\n\n# Enables or disables console logging\n# [type: bool, advanced: false, range: {false, true}, default: true]\nlog_to_console: true\n\n# Solution file\n# [type: string, advanced: false, default: \"\"]\nsolution_file: \"\"\n\n# Log file\n# [type: string, advanced: false, default: \"\"]\nlog_file: \"\"\n\n# Write the primal and dual solution to a file\n# [type: bool, advanced: false, range: {false, true}, default: false]\nwrite_solution_to_file: false\n\n# Write the solution in style: 0=>Raw (computer-readable); 1=>Pretty (human-readable) \n# [type: HighsInt, advanced: false, range: {0, 2}, default: 0]\nwrite_solution_style: 0\n\n# Write model file\n# [type: string, advanced: false, default: \"\"]\nwrite_model_file: \"\"\n\n# Write the model to a file\n# [type: bool, advanced: false, range: {false, true}, default: false]\nwrite_model_to_file: false\n\n# Whether symmetry should be detected\n# [type: bool, advanced: false, range: {false, true}, default: true]\nmip_detect_symmetry: true\n\n# MIP solver max number of nodes\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nmip_max_nodes: 2147483647\n\n# MIP solver max number of nodes where estimate is above cutoff bound\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nmip_max_stall_nodes: 2147483647\n\n# MIP solver max number of leave nodes\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 2147483647]\nmip_max_leaves: 2147483647\n\n# limit on the number of improving solutions found to stop the MIP solver prematurely\n# [type: HighsInt, advanced: false, range: {1, 2147483647}, default: 2147483647]\nmip_max_improving_sols: 2147483647\n\n# maximal age of dynamic LP rows before they are removed from the LP relaxation\n# [type: HighsInt, advanced: false, range: {0, 32767}, default: 10]\nmip_lp_age_limit: 10\n\n# maximal age of rows in the cutpool before they are deleted\n# [type: HighsInt, advanced: false, range: {0, 1000}, default: 30]\nmip_pool_age_limit: 30\n\n# soft limit on the number of rows in the cutpool for dynamic age adjustment\n# [type: HighsInt, advanced: false, range: {1, 2147483647}, default: 10000]\nmip_pool_soft_limit: 10000\n\n# minimal number of observations before pseudo costs are considered reliable\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 8]\nmip_pscost_minreliable: 8\n\n# minimal number of entries in the cliquetable before neighborhood queries of the conflict graph use parallel processing\n# [type: HighsInt, advanced: false, range: {0, 2147483647}, default: 100000]\nmip_min_cliquetable_entries_for_parallelism: 100000\n\n# MIP solver reporting level\n# [type: HighsInt, advanced: false, range: {0, 2}, default: 1]\nmip_report_level: 1\n\n# MIP feasibility tolerance\n# [type: double, advanced: false, range: [1e-10, inf], default: 1e-06]\nmip_feasibility_tolerance: 1e-06\n\n# effort spent for MIP heuristics\n# [type: double, advanced: false, range: [0, 1], default: 0.05]\nmip_heuristic_effort: 0.05\n\n# tolerance on relative gap, |ub-lb|/|ub|, to determine whether optimality has been reached for a MIP instance\n# [type: double, advanced: false, range: [0, inf], default: 0.0001]\nmip_rel_gap: 0.0001\n\n# tolerance on absolute gap of MIP, |ub-lb|, to determine whether optimality has been reached for a MIP instance\n# [type: double, advanced: false, range: [0, inf], default: 1e-06]\nmip_abs_gap: 1e-06\n\n# Output development messages: 0 => none; 1 => info; 2 => verbose\n# [type: HighsInt, advanced: true, range: {0, 3}, default: 0]\nlog_dev_level: 0\n\n# Run the crossover routine for IPX\n# [type: string, advanced: \"on\", range: {\"off\", \"on\"}, default: \"off\"]\nrun_crossover: \"off\"\n\n# Allow ModelStatus::kUnboundedOrInfeasible\n# [type: bool, advanced: true, range: {false, true}, default: false]\nallow_unbounded_or_infeasible: false\n\n# Use relaxed implied bounds from presolve\n# [type: bool, advanced: true, range: {false, true}, default: false]\nuse_implied_bounds_from_presolve: false\n\n# Prevents LP presolve steps for which postsolve cannot maintain a basis\n# [type: bool, advanced: true, range: {false, true}, default: true]\nlp_presolve_requires_basis_postsolve: true\n\n# Use the free format MPS file reader\n# [type: bool, advanced: true, range: {false, true}, default: true]\nmps_parser_type_free: true\n\n# For multiple N-rows in MPS files: delete rows / delete entries / keep rows (-1/0/1)\n# [type: HighsInt, advanced: true, range: {-1, 1}, default: -1]\nkeep_n_rows: -1\n\n# Scaling factor for costs\n# [type: HighsInt, advanced: true, range: {-20, 20}, default: 0]\ncost_scale_factor: 0\n\n# Largest power-of-two factor permitted when scaling the constraint matrix\n# [type: HighsInt, advanced: true, range: {0, 30}, default: 20]\nallowed_matrix_scale_factor: 20\n\n# Largest power-of-two factor permitted when scaling the costs\n# [type: HighsInt, advanced: true, range: {0, 20}, default: 0]\nallowed_cost_scale_factor: 0\n\n# Strategy for permuting before simplex\n# [type: HighsInt, advanced: true, range: {-1, 1}, default: -1]\nsimplex_permute_strategy: -1\n\n# Max level of dual simplex cleanup\n# [type: HighsInt, advanced: true, range: {0, 2147483647}, default: 1]\nmax_dual_simplex_cleanup_level: 1\n\n# Max level of dual simplex phase 1 cleanup\n# [type: HighsInt, advanced: true, range: {0, 2147483647}, default: 2]\nmax_dual_simplex_phase1_cleanup_level: 2\n\n# Strategy for PRICE in simplex\n# [type: HighsInt, advanced: true, range: {0, 3}, default: 3]\nsimplex_price_strategy: 3\n\nStrategy for solving unscaled LP in simplex\n[type: HighsInt, advanced: true, range: {0, 2}, default: 1]\nsimplex_unscaled_solution_strategy: 1\n\nPerform initial basis condition check in simplex\n[type: bool, advanced: true, range: {false, true}, default: true]\nsimplex_initial_condition_check: true\n\nNo unnecessary refactorization on simplex rebuild\n[type: bool, advanced: true, range: {false, true}, default: true]\nno_unnecessary_rebuild_refactor: true\n\nTolerance on initial basis condition in simplex\n[type: double, advanced: true, range: [1, inf], default: 1e+14]\nsimplex_initial_condition_tolerance: 1e+14\n\nTolerance on solution error when considering refactorization on simplex rebuild\n[type: double, advanced: true, range: [-inf, inf], default: 1e-08]\nrebuild_refactor_solution_error_tolerance: 1e-08\n\nTolerance on dual steepest edge weight errors\n[type: double, advanced: true, range: [0, inf], default: inf]\ndual_steepest_edge_weight_error_tolerance: Inf\n\nThreshold on dual steepest edge weight errors for Devex switch\n[type: double, advanced: true, range: [1, inf], default: 10]\ndual_steepest_edge_weight_log_error_threshold: 10.0\n\nDual simplex cost perturbation multiplier: 0 => no perturbation\n[type: double, advanced: true, range: [0, inf], default: 1]\ndual_simplex_cost_perturbation_multiplier: 1.0\n\nPrimal simplex bound perturbation multiplier: 0 => no perturbation\n[type: double, advanced: true, range: [0, inf], default: 1]\nprimal_simplex_bound_perturbation_multiplier: 1.0\n\nDual simplex pivot growth tolerance\n[type: double, advanced: true, range: [1e-12, inf], default: 1e-09]\ndual_simplex_pivot_growth_tolerance: 1e-09\n\nMatrix factorization pivot threshold for substitutions in presolve\n[type: double, advanced: true, range: [0.0008, 0.5], default: 0.01]\npresolve_pivot_threshold: 0.01\n\nMaximal fillin allowed for substitutions in presolve\n[type: HighsInt, advanced: true, range: {0, 2147483647}, default: 10]\npresolve_substitution_maxfillin: 10\n\nMatrix factorization pivot threshold\n[type: double, advanced: true, range: [0.0008, 0.5], default: 0.1]\nfactor_pivot_threshold: 0.1\n\nMatrix factorization pivot tolerance\n[type: double, advanced: true, range: [0, 1], default: 1e-10]\nfactor_pivot_tolerance: 1e-10\n\nTolerance to be satisfied before IPM crossover will start\n[type: double, advanced: true, range: [1e-12, inf], default: 1e-08]\nstart_crossover_tolerance: 1e-08\n\nUse original HFactor logic for sparse vs hyper-sparse TRANs\n[type: bool, advanced: true, range: {false, true}, default: true]\nuse_original_HFactor_logic: true\n\nCheck whether LP is candidate for LiDSE\n[type: bool, advanced: true, range: {false, true}, default: true]\nless_infeasible_DSE_check: true\n\nUse LiDSE if LP has right properties\n[type: bool, advanced: true, range: {false, true}, default: true]\nless_infeasible_DSE_choose_row: true\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-Gurobi","page":"Solver Configurations","title":"Configuring Gurobi","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_gurobi.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_gurobi-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_gurobi","text":"configure_gurobi(solver_settings_path::String)\n\nReads user-specified solver settings from gurobi_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes Gurobi optimizer instance to be used in the GenX.generate_model() method.\n\nThe Gurobi optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nFeasibilityTol = 1e-6 (Constraint (primal) feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/feasibilitytol.html)\nOptimalityTol = 1e-4 (Dual feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/optimalitytol.html#parameter:OptimalityTol)\nPresolve = -1 (Controls presolve level. See https://www.gurobi.com/documentation/8.1/refman/presolve.html)\nAggFill = -1 (Allowed fill during presolve aggregation. See https://www.gurobi.com/documentation/8.1/refman/aggfill.html#parameter:AggFill)\nPreDual = -1 (Presolve dualization. See https://www.gurobi.com/documentation/8.1/refman/predual.html#parameter:PreDual)\nTimeLimit = Inf\t(Limits total time solver. See https://www.gurobi.com/documentation/8.1/refman/timelimit.html)\nMIPGap = 1e-4 (Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). See https://www.gurobi.com/documentation/8.1/refman/mipgap2.html)\nCrossover = -1 (Barrier crossver strategy. See https://www.gurobi.com/documentation/8.1/refman/crossover.html#parameter:Crossover)\nMethod = -1\t(Algorithm used to solve continuous models (including MIP root relaxation). See https://www.gurobi.com/documentation/8.1/refman/method.html)\nBarConvTol = 1e-8 (Barrier convergence tolerance (determines when barrier terminates). See https://www.gurobi.com/documentation/8.1/refman/barconvtol.html)\nNumericFocus = 0 (Numerical precision emphasis. See https://www.gurobi.com/documentation/8.1/refman/numericfocus.html)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-CPLEX","page":"Solver Configurations","title":"Configuring CPLEX","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_cplex.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_cplex-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_cplex","text":"configure_cplex(solver_settings_path::String)\n\nReads user-specified solver settings from cplex_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes CPLEX optimizer instance.\n\nThe optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nFeasib_Tol,\nsets CPX_PARAM_EPRHS. Control the primal feasibility tolerance. Default is 1e-6.\nOptimal_Tol,\nsets CPX_PARAM_EPOPT. Control the optimality tolerance. Default is 1e-4.\nAggFill,\nsets CPX_PARAM_AGGFILL. Control the allowed fill during presolve aggregation. Default is 10.\nPreDual,\nsets CPX_PARAM_PREDUAL. Decides whether presolve should pass the primal or dual linear programming problem to the LP optimization algorithm. Default is 0.\nTimeLimit,\nsets CPX_PARAM_TILIM. Limits total solver time. Default is 1e+75.\nMIPGap,\nsets CPX_PARAM_EPGAP Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). Default is 1e-3.\nMethod,\nsets CPX_PARAM_LPMETHOD. Algorithm used to solve continuous models (including MIP root relaxation) Default is 0.\nBarConvTol,\nsets CPX_PARAM_BAREPCOMP. Barrier convergence tolerance (determines when barrier terminates). Default is 1e-8.\nNumericFocus,\nsets CPX_PARAM_NUMERICALEMPHASIS. Numerical precision emphasis. Default is 0.\nBarObjRng,\nsets CPX_PARAM_BAROBJRNG. The maximum absolute value of the objective function. Default is 1e+75.\nSolutionType,\nsets CPX_PARAM_SOLUTIONTYPE. Solution type for LP or QP. Default is 2.\n\nThe optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nAny other attributes in the settings file (which typically start with CPX_PARAM_) will also be passed to the solver.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-Clp","page":"Solver Configurations","title":"Configuring Clp","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_clp.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_clp-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_clp","text":"configure_clp(solver_settings_path::String)\n\nReads user-specified solver settings from clp_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes Clp optimizer instance to be used in the GenX.generate_model() method.\n\nThe Clp optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nPrimalTolerance = 1e-7 (Primal feasibility tolerance)\nDualTolerance = 1e-7 (Dual feasibility tolerance)\nDualObjectiveLimit = 1e308 (When using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit)\nMaximumIterations = 2147483647 (Terminate after performing this number of simplex iterations)\nMaximumSeconds = -1.0\t(Terminate after this many seconds have passed. A negative value means no time limit)\nLogLevel = 1 (Set to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output)\nPresolveType = 0 (Set to 1 to disable presolve)\nSolveType = 5 (Solution method: dual simplex (0), primal simplex (1), sprint (2), barrier with crossover (3), barrier without crossover (4), automatic (5))\nInfeasibleReturn = 0 (Set to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well))\nScaling = 3 (0 0ff, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic (later))\nPerturbation = 100 (switch on perturbation (50), automatic (100), don't try perturbing (102))\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-Cbc","page":"Solver Configurations","title":"Configuring Cbc","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_cbc.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_cbc-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_cbc","text":"configure_cbc(solver_settings_path::String)\n\nReads user-specified solver settings from cbc_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes Cbc optimizer instance to be used in the GenX.generate_model() method.\n\nThe Cbc optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nseconds = 1e-6\nlogLevel = 1e-6\nmaxSolutions = -1\nmaxNodes = -1\nallowableGap = -1\nratioGap = Inf\nthreads = 1\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solver_configuration_api/#Configuring-SCIP","page":"Solver Configurations","title":"Configuring SCIP","text":"","category":"section"},{"location":"Model_Reference/solver_configuration_api/","page":"Solver Configurations","title":"Solver Configurations","text":"Modules = [GenX]\nPages = [\"configure_scip.jl\"]","category":"page"},{"location":"Model_Reference/solver_configuration_api/#GenX.configure_scip-Tuple{String, Any}","page":"Solver Configurations","title":"GenX.configure_scip","text":"configure_scip(solver_settings_path::String)\n\nReads user-specified solver settings from scip_settings.yml in the directory specified by the string solver_settings_path.\n\nReturns a MathOptInterface.OptimizerWithAttributes SCIP optimizer instance to be used in the GenX.generate_model() method.\n\nThe SCIP optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:\n\nDispverblevel = 0\nlimitsgap = 0.05\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/policies/#Emission-mitigation-policies","page":"Policies","title":"Emission mitigation policies","text":"","category":"section"},{"location":"Model_Reference/policies/#Capacity-Reserve-Margin","page":"Policies","title":"Capacity Reserve Margin","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.cap_reserve_margin!","category":"page"},{"location":"Model_Reference/policies/#GenX.cap_reserve_margin!","page":"Policies","title":"GenX.cap_reserve_margin!","text":"cap_reserve_margin!(EP::Model, inputs::Dict, setup::Dict)\n\nInstead of modeling capacity reserve margin requirement (a.k.a. capacity market or resource adequacy requirement) using an annual constraint, we model each requirement with hourly constraint by simulating the activation of the capacity obligation. We define capacity reserve margin constraint for subsets of zones, z in mathcalZ^CRM_p, and each subset stands for a locational deliverability area (LDA) or a reserve sharing group. For thermal resources, the available capacity is the total capacity in the LDA derated by the outage rate, epsilon_yzp^CRM. For variable renewable energy (y in mathcalVRE), the available capacity is the maximum discharge potential in time step t derated by the derating factor. For standalone storage and co-located VRE and storage resources (y in mathcalO cup mathcalVS) the available capacity is the net injection into the transmission network plus the net virtual injection corresponding to charge held in reserve, derated by the derating factor. For information on how each component contributes to the capacity reserve margin formulation for co-located VRE and storage resources, see vre_stor_capres!(). For flexible demand resources (y in mathcalDF), the available capacity is the net injection into the transmission network in time step t derated by the derating factor, also stored in the parameter, epsilon_yzp^CRM. If the imported capacity is eligible to provide capacity to the CRM constraint, the inbound powerflow on all lines mathcalL_p^in in time step t will be derated to form the available capacity from outside of the LDA. The reverse is true as well: the outbound derated powerflow on all lines mathcalL_p^out in time step t is taken out from the total available capacity. The derating factor should be equal to the expected availability of the resource during periods when the capacity reserve constraint is binding (e.g. accounting for forced outages during supply constrained periods) and is similar to derating factors used in the capacity markets. On top of the flexible demand resources, demand curtailment can also provide capacity (i.e., demand response or load management). We allow all segments of voluntary demand curtailment, s geq 2 in S, to contribute to capacity requirements. The first segment s = 1 in S corresponds to involuntary demand curtailment or emergency load shedding at the price cap or value of lost demand, and thus does not contribute to reserve requirements. Note that the time step-weighted sum of the shadow prices of this constraint corresponds to the capacity market payments reported by ISOs with mandate capacity market mechanism.\n\nbeginaligned\n\t sum_z in mathcalZ^CRM_p Big( sum_y in mathcalH epsilon_yzp^CRM times Delta^texttotal_yz + sum_y in mathcalVRE epsilon_yzp^CRM times rho^max_yzt \n\t + sum_y in mathcalO epsilon_yzp^CRM times left(Theta_yzt + Theta^CRM_ozt - Pi^CRM_ozt - Pi_yzt right) + sum_y in mathcalDF epsilon_yzp^CRM times left(Pi_yzt - Theta_yzt right) \n\t + sum_y in mathcalVS^pv (epsilon_yzp^CRM times eta^inverter_yz times rho^maxpv_yzt times Delta^totalpv_yz) \n\t + sum_y in mathcalVS^wind (epsilon_yzp^CRM times rho^maxwind_yzt times Delta^totalwind_yz) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis (epsilon_yzp^CRM times eta^inverter_yz times (Theta^dc_yzt + Theta^CRMdc_yzt)) \n + sum_y in mathcalVS^symac cup mathcalVS^asymacdis (epsilon_yzp^CRM times (Theta^ac_yzt + Theta^CRMac_yzt)) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times fracPi^dc_yzt + Pi^CRMdc_yzteta^inverter_yz) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times (Pi^ac_yzt + Pi^CRMac_yzt)) \n\t + sum_l in mathcalL_p^in epsilon_yzp^CRM times Phi_lt - sum_l in mathcalL_p^out epsilon_yzp^CRM times Phi_lt\n \t+ sum_s geq 2 Lambda_stz Big) \n \t geq sum_z in mathcalZ^CRM_p left( left(1 + RM_zp^CRM right) times D_zt right) hspace1 cm forall t in mathcalT forall pin mathcalP^CRM\nendaligned\n\nNote that multiple capacity reserve margin requirements can be specified covering different individual zones or aggregations of zones, where the total number of constraints is specified by the GenX settings parameter CapacityReserveMargin (where this parameter should be an integer value > 0). The expressions establishing the capacity reserve margin contributions of each technology class are included in their respective technology modules.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#CO_2-Constraint-Policy","page":"Policies","title":"CO_2 Constraint Policy","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.co2_cap!","category":"page"},{"location":"Model_Reference/policies/#GenX.co2_cap!","page":"Policies","title":"GenX.co2_cap!","text":"co2_cap!(EP::Model, inputs::Dict, setup::Dict)\n\nThis policy constraints mimics the CO_2 emissions cap and permit trading systems, allowing for emissions trading across each zone for which the cap applies. The constraint p in mathcalP^CO_2 can be flexibly defined for mass-based or rate-based emission limits for one or more model zones, where zones can trade CO_2 emissions permits and earn revenue based on their CO_2 allowance. Note that if the model is fully linear (e.g. no unit commitment or linearized unit commitment), the dual variable of the emissions constraints can be interpreted as the marginal CO_2 price per tonne associated with the emissions target. Alternatively, for integer model formulations, the marginal CO_2 price can be obtained after solving the model with fixed integer/binary variables.\n\nThe CO_2 emissions limit can be defined in one of the following ways: a) a mass-based limit defined in terms of annual CO_2 emissions budget (in million tonnes of CO2), b) a demand-side rate-based limit defined in terms of tonnes CO_2 per MWh of fulfilled demand and c) a generation-side rate-based limit defined in terms of tonnes CO_2 per MWh of generation.\n\nMass-based emissions constraint\n\nMass-based emission limits are implemented in the following expression. For each constraint, p in mathcalP^CO_2_mass, we define a set of zones z in mathcalZ^CO_2_pmass that can trade CO_2 allowance. Input data for each constraint p in mathcalP^CO_2_mass requires the CO_2 allowance/ budget for each model zone, epsilon^CO_2_zp mass, to be provided in terms of million metric tonnes. For every generator y, the parameter epsilon_yz^CO_2 reflects the specific CO_2 emission intensity in tCO_2/MWh associated with its operation. The resulting constraint is given as:\n\nbeginaligned\n sum_z in mathcalZ^CO_2_pmass sum_y in mathcalG sum_t in mathcalT left(epsilon_yz^CO_2 times omega_t times Theta_yzt right)\n leq sum_z in mathcalZ^CO_2_pmass epsilon^CO_2_zp mass hspace1 cm forall p in mathcalP^CO_2_mass\nendaligned\n\nIn the above constraint, we include both power discharge and charge term for each resource to account for the potential for CO_2 emissions (or removal when considering negative emissions technologies) associated with each step. Note that if a limit is applied to each zone separately, then the set mathcalZ^CO_2_pmass will contain only one zone with no possibility of trading. If a system-wide emission limit constraint is applied, then mathcalZ^CO_2_pmass will be equivalent to a set of all zones.\n\nDemand-side rate-based emissions constraint\n\nWe modify the right hand side of the above mass-based constraint, p in mathcalP^CO_2_demand, to set emissions target based on a CO_2 emission rate limit in tCO_2/MWh times the total demand served (fulfilled) in each zone. In the following constraint, total demand served takes into account non-served energy and storage related losses. Here, epsilon_zpdemand^maxCO_2 denotes the emission limit in terms on tCO_2/MWh.\n\nbeginaligned\n sum_z in mathcalZ^CO_2_pdemand sum_y in mathcalG sum_t in mathcalT left(epsilon_yz^CO_2 times omega_t times Theta_ytz right)\n leq sum_z in mathcalZ^CO_2_pdemand sum_t in mathcalT\n left(epsilon_zpdemand^CO_2 times omega_t times D_zt right) \n + sum_z in mathcalZ^CO_2_pdemand sum_y in mathcalO cup mathcalVS^stor sum_t in mathcalT\n left(epsilon_zpdemand^CO_2 times omega_t times left(Pi_ytz - Theta_ytz right) right) \n - sum_z in mathcalZ^CO_2_pdemand sum_s in mathcalS sum_t in mathcalT left(epsilon_zpdemand^CO_2 times omega_t times Lambda_sztright) hspace1 cm forall p in mathcalP^CO_2_demand\nendaligned\n\nGenerator-side emissions rate-based constraint\n\nSimilarly, a generation based emission constraint is defined by setting the emission limit based on the total generation times the carbon emission rate limit in tCO_2/MWh of the region. The resulting constraint is given as:\n\nbeginaligned\nsum_z in mathcalZ^CO_2_pgen sum_y in mathcalG sum_t in mathcalT left(epsilon_yz^CO_2 times omega_t times Theta_ytz right) \n leq sum_z in mathcalZ^CO_2_pgen sum_y in mathcalG sum_t in mathcalT left(epsilon_zpgen^CO_2 times omega_t times Theta_ytz right) hspace1 cm forall p in mathcalP^CO_2_gen\nendaligned\n\nNote that the generator-side rate-based constraint can be used to represent a fee-rebate (``feebate'') system: the dirty generators that emit above the bar (epsilon_zpgen^maxCO_2) have to buy emission allowances from the emission regulator in the region z where they are located; in the same vein, the clean generators get rebates from the emission regulator at an emission allowance price being the dual variable of the emissions rate constraint.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#Energy-Share-Requirement","page":"Policies","title":"Energy Share Requirement","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.load_energy_share_requirement!\nGenX.energy_share_requirement!","category":"page"},{"location":"Model_Reference/policies/#GenX.load_energy_share_requirement!","page":"Policies","title":"GenX.load_energy_share_requirement!","text":"load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#GenX.energy_share_requirement!","page":"Policies","title":"GenX.energy_share_requirement!","text":"energy_share_requirement!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function establishes constraints that can be flexibily applied to define alternative forms of policies that require generation of a minimum quantity of megawatt-hours from a set of qualifying resources, such as renewable portfolio standard (RPS) or clean electricity standard (CES) policies prevalent in different jurisdictions. These policies usually require that the annual MWh generation from a subset of qualifying generators has to be higher than a pre-specified percentage of demand from qualifying zones. The implementation allows for user to define one or multiple RPS/CES style minimum energy share constraints, where each constraint can cover different combination of model zones to mimic real-world policy implementation (e.g. multiple state policies, multiple RPS tiers or overlapping RPS and CES policies). The number of energy share requirement constraints is specified by the user by the value of the GenX settings parameter EnergyShareRequirement (this value should be an integer >=0). For each constraint p in mathcalP^ESR, we define a subset of zones z in mathcalZ^ESR_p subset mathcalZ that are eligible for trading renewable/clean energy credits to meet the corresponding renewable/clean energy requirement. For each energy share requirement constraint p in mathcalP^ESR, we specify the share of total demand in each eligible model zone, z in mathcalZ^ESR_p, that must be served by qualifying resources, mathcalG_p^ESR subset mathcalG:\n\nbeginaligned\nsum_z in mathcalZ_p^ESR sum_y in mathcalG_p^ESR sum_t in mathcalT (omega_t times Theta_yzt) geq sum_z in mathcalZ^ESR_p sum_t in mathcalT (mu_pz^ESR times omega_t times D_zt) + \nsum_y in mathcalVS^stor sum_z in mathcalZ^ESR_p sum_t in mathcalT left(mu_pz^ESR times omega_t times (fracPi^dc_yzteta_yz^inverter + Pi^ac_yzt - eta_yz^inverter times Theta^dc_yzt - Theta^ac_yzt) right) + \nsum_y in mathcalO sum_z in mathcalZ^ESR_p sum_t in mathcalT left(mu_pz^ESR times omega_t times (Pi_yzt - Theta_yzt) right) hspace1 cm forall p in mathcalP^ESR \nendaligned\n\nThe final two terms in the summation above adds roundtrip storage losses to the total demand to which the energy share obligation applies. This term is included in the constraint if the GenX setup parameter StorageLosses=1. If StorageLosses=0, this term is removed from the constraint. In practice, most existing renewable portfolio standard policies do not account for storage losses when determining energy share requirements. However, with 100% RPS or CES policies enacted in several jurisdictions, policy makers may wish to include storage losses in the minimum energy share, as otherwise there will be a difference between total generation and total demand that will permit continued use of non-qualifying resources (e.g. emitting generators).\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#Minimum-Capacity-Requirement","page":"Policies","title":"Minimum Capacity Requirement","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"GenX.minimum_capacity_requirement!","category":"page"},{"location":"Model_Reference/policies/#GenX.minimum_capacity_requirement!","page":"Policies","title":"GenX.minimum_capacity_requirement!","text":"minimum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)\n\nThe minimum capacity requirement constraint allows for modeling minimum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement p in mathcalP^MinCapReq, we model the policy with the following constraint.\n\nbeginaligned\nsum_y in mathcalG sum_z in mathcalZ left( epsilon_yzp^MinCapReq times Delta^texttotal_yz right) geq REQ_p^MinCapReq hspace1 cm forall p in mathcalP^MinCapReq\nendaligned\n\nNote that epsilon_yzp^MinCapReq is the eligiblity of a generator of technology y in zone z of requirement p and will be equal to 1 for eligible generators and will be zero for ineligible resources. The dual value of each minimum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.\n\nAlso note that co-located VRE and storage resources, there are three different components \tthat minimum capacity requirements can be created for. The capacity of solar PV (in AC terms \tsince the capacity is multiplied by the inverter efficiency), the capacity of wind, and the discharge \tcapacity of storage (power to energy ratio times the energy capacity) can all have minimum capacity \trequirements.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/policies/#Maximum-Capacity-Requirement","page":"Policies","title":"Maximum Capacity Requirement","text":"","category":"section"},{"location":"Model_Reference/policies/","page":"Policies","title":"Policies","text":"Modules = [GenX]\nPages = [\"maximum_capacity_requirement.jl\"]","category":"page"},{"location":"Model_Reference/policies/#GenX.load_maximum_capacity_requirement!-Tuple{AbstractString, Dict, Dict}","page":"Policies","title":"GenX.load_maximum_capacity_requirement!","text":"load_maximum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)\n\nRead input parameters related to maximum capacity requirement constraints (e.g. technology specific deployment mandates)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/policies/#GenX.maximum_capacity_requirement!-Tuple{JuMP.Model, Dict, Dict}","page":"Policies","title":"GenX.maximum_capacity_requirement!","text":"maximum_capacity_requirement!(EP::Model, inputs::Dict, setup::Dict)\n\nThe maximum capacity requirement constraint allows for modeling maximum deployment of a certain technology or set of eligible technologies across the eligible model zones and can be used to mimic policies supporting specific technology build out (i.e. capacity deployment targets/mandates for storage, offshore wind, solar etc.). The default unit of the constraint is in MW. For each requirement p in mathcalP^MaxCapReq, we model the policy with the following constraint.\n\nbeginaligned\nsum_y in mathcalG sum_z in mathcalZ left( epsilon_yzp^MaxCapReq times Delta^texttotal_yz right) leq REQ_p^MaxCapReq hspace1 cm forall p in mathcalP^MaxCapReq\nendaligned\n\nNote that epsilon_yzp^MaxCapReq is the eligiblity of a generator of technology y in zone z of requirement p and will be equal to 1 for eligible generators and will be zero for ineligible resources. The dual value of each maximum capacity constraint can be interpreted as the required payment (e.g. subsidy) per MW per year required to ensure adequate revenue for the qualifying resources.\n\n\n\n\n\n","category":"method"},{"location":"limitations_genx/#Limitations-of-the-GenX-Model","page":"Limitation of GenX","title":"Limitations of the GenX Model","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"While the benefits of an openly available generation and transmission expansion model are high, many approximations have been made due to missing data or to manage computational tractability. The assumptions of the GenX model are listed below. It serves as a caveat to the user and as an encouragement to improve the approximations.","category":"page"},{"location":"limitations_genx/#1.-Time-period","page":"Limitation of GenX","title":"1. Time period","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX makes the simplifying assumption that each time period contains n copies of a single, representative year. GenX optimizes generation and transmission capacity for just this characteristic year within each time period, assuming the results for different years in the same time period are identical. However, the GenX objective function accounts only for the cost of the final model time period.","category":"page"},{"location":"limitations_genx/#2.-Cost","page":"Limitation of GenX","title":"2. Cost","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"The GenX objective function assumes that the cost of powerplants is specified in the unit of currency per unit of capacity. GenX also assumes that the capital cost of technologies is paid through loans.","category":"page"},{"location":"limitations_genx/#3.Market","page":"Limitation of GenX","title":"3.Market","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX is a bottom-up (technology-explicit), partial equilibrium model that assumes perfect markets for commodities. In other words, each commodity is produced such that the sum of producer and consumer surplus is maximized.","category":"page"},{"location":"limitations_genx/#4.-Technology","page":"Limitation of GenX","title":"4. Technology","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"Behavioral response and acceptance of new technology are often modeled simplistically as a discount rate or by externally fixing the technology capacity. A higher, technology-specific discount rate represents consumer reluctance to accept newer technologies.","category":"page"},{"location":"limitations_genx/#5.-Uncertainty","page":"Limitation of GenX","title":"5. Uncertainty","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"Because each model realization assumes a particular state of the world based on the input values drawn, the parameter uncertainty is propagated through the model in the case of myopic model runs.","category":"page"},{"location":"limitations_genx/#6.-Decision-making","page":"Limitation of GenX","title":"6. Decision-making","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX assumes rational decision making, with perfect information and perfect foresight, and simultaneously optimizes all decisions over the user-specified time horizon.","category":"page"},{"location":"limitations_genx/#7.-Demand","page":"Limitation of GenX","title":"7. Demand","text":"","category":"section"},{"location":"limitations_genx/","page":"Limitation of GenX","title":"Limitation of GenX","text":"GenX assumes price-elastic demand segments that are represented using piece-wise approximation rather than an inverse demand curve to keep the model linear.","category":"page"},{"location":"Public_API/public_api/#Public-Documentation","page":"Public API","title":"Public Documentation","text":"","category":"section"},{"location":"Public_API/public_api/","page":"Public API","title":"Public API","text":"Documentation for GenX public interface.","category":"page"},{"location":"Public_API/public_api/","page":"Public API","title":"Public API","text":"GenX.run_genx_case!\nGenX.configure_settings\nGenX.configure_solver\nGenX.load_inputs\nGenX.load_dataframe\nGenX.generate_model\nGenX.solve_model\nGenX.write_outputs\nGenX.mga","category":"page"},{"location":"Public_API/public_api/#GenX.run_genx_case!","page":"Public API","title":"GenX.run_genx_case!","text":"run_genx_case!(case::AbstractString, optimizer::Any=HiGHS.Optimizer)\n\nRun a GenX case with the specified optimizer. The optimizer can be any solver supported by MathOptInterface.\n\nArguments\n\ncase::AbstractString: the path to the case folder\noptimizer::Any: the optimizer instance to be used in the optimization model\n\nExample\n\nrun_genx_case!(\"path/to/case\", HiGHS.Optimizer)\n\nrun_genx_case!(\"path/to/case\", Gurobi.Optimizer)\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.configure_settings","page":"Public API","title":"GenX.configure_settings","text":"configure_settings(settings_path::String, output_settings_path::String)\n\nReads in the settings from the genx_settings.yml and output_settings.yml YAML files and merges them with the default settings. It then validates the settings and returns the settings dictionary.\n\nArguments\n\nsettings_path::String: The path to the settings YAML file.\noutput_settings_path::String: The path to the output settings YAML file.\n\nReturns\n\nsettings::Dict: The settings dictionary.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.configure_solver","page":"Public API","title":"GenX.configure_solver","text":"configure_solver(solver_settings_path::String, optimizer::Any)\n\nThis method returns a solver-specific MathOptInterface.OptimizerWithAttributes optimizer instance to be used in the GenX.generate\\_model() method.\n\nArguments\n\nsolver_settings_path::String: specifies the path to the directory that contains the settings YAML file for the specified solver.\noptimizer::Any: the optimizer instance to be configured.\n\nCurrently supported solvers include: \"Gurobi\", \"CPLEX\", \"Clp\", \"Cbc\", or \"SCIP\"\n\nReturns\n\noptimizer::MathOptInterface.OptimizerWithAttributes: the configured optimizer instance.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.load_inputs","page":"Public API","title":"GenX.load_inputs","text":"load_inputs(setup::Dict,path::AbstractString)\n\nLoads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function\n\ninputs: setup - dict object containing setup parameters path - string path to working directory\n\nreturns: Dict (dictionary) object containing all data inputs\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.load_dataframe","page":"Public API","title":"GenX.load_dataframe","text":"load_dataframe(path::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\nload_dataframe(dir::AbstractString, base::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.generate_model","page":"Public API","title":"GenX.generate_model","text":"generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAttributes,modeloutput = nothing)\n\nThis function sets up and solves a constrained optimization model of electricity system capacity expansion and operation problem and extracts solution variables for later processing.\n\nIn addition to calling a number of other modules to create constraints for specific resources, policies, and transmission assets, this function initializes two key expressions that are successively expanded in each of the resource-specific modules: (1) the objective function; and (2) the zonal power balance expression. These two expressions are the only expressions which link together individual modules (e.g. resources, transmission assets, policies), which otherwise are self-contained in defining relevant variables, expressions, and constraints.\n\nObjective Function\n\nThe objective function of GenX minimizes total annual electricity system costs over the following six components shown in the equation below:\n\nbeginaligned\n\tsum_y in mathcalG sum_z in mathcalZ\n\tleft( (pi^INVEST_yz times overlineOmega^size_yz times Omega_yz)\n\t+ (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right) + notag \n\tsum_y in mathcalO sum_z in mathcalZ\n\tleft( (pi^INVESTenergy_yz times Omega^energy_yz)\n\t+ (pi^FOMenergy_yz times Delta^totalenergy_yz)right) + notag \n\tsum_y in mathcalO^asym sum_z in mathcalZ\n\tleft( (pi^INVESTcharge_yz times Omega^charge_yz)\n\t+ (pi^FOMcharge_yz times Delta^totalcharge_yz)right) + notag \n\t sum_y in mathcalG sum_z in mathcalZ sum_t in mathcalT left( omega_ttimes(pi^VOM_yz + pi^FUEL_yz)times Theta_yztright) + sum_y in mathcalO cup DF sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMcharge_yz times Pi_yztright) +notag \n\tsum_s in mathcalS sum_z in mathcalZ sum_t in mathcalTleft(omega_t times n_s^slope times Lambda_sztright) + sum_t in mathcalT left(omega_t times pi^unmet_rsv times r^unmet_tright) notag \n\tsum_y in mathcalH sum_z in mathcalZ sum_t in mathcalTleft(omega_t times pi^START_yz times chi_sztright) + notag \n\t sum_l in mathcalLleft(pi^TCAP_l times bigtriangleupvarphi^max_lright)\nendaligned\n\nThe first summation represents the fixed costs of generation/discharge over all zones and technologies, which refects the sum of the annualized capital cost, pi^INVEST_yz, times the total new capacity added (if any), plus the Fixed O&M cost, pi^FOM_yz, times the net installed generation capacity, overlineOmega^size_yz times Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources. This term includes the sum of the annualized energy capital cost, pi^INVESTenergy_yz, times the total new energy capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed energy storage capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components (mathcalO^asym). This term includes the sum of the annualized charging power capital cost, pi^INVESTcharge_yz, times the total new charging power capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed charging power capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe fourth and fifth summations corresponds to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, pi^FUEL_yz (if any), plus variable O&M cost, pi^VOM_yz times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, yinmathcalDF) in time step t, Theta_yzt, and the weight of each time step t, omega_t, where omega_t is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, t such that the sum of omega_t forall t in T = 8760, approximating annual operating costs. The fifth summation represents the variable charging O&M cost, pi^VOMcharge_yz times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step t , Pi_yzt and the annual weight of time step t,omega_t.\n\nThe sixth summation represents the total cost of unserved demand across all segments s of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), n_s^slope, times the amount of non-served energy, Lambda_yzt, for each segment on each zone during each time step (weighted by omega_t).\n\nThe seventh summation represents the total cost of not meeting hourly operating reserve requirements, where pi^unmet_rsv is the cost penalty per unit of non-served reserve requirement, and r^unmet_t is the amount of non-served reserve requirement in each time step (weighted by omega_t).\n\nThe eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. y in mathcalUC), equal to the cost of start-up, pi^START_yz, times the number of startup events, chi_yzt, for the cluster of units in each zone and time step (weighted by omega_t).\n\nThe last term corresponds to the transmission reinforcement or construction costs, for each transmission line in the model. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, pi^TCAP_l, times the additional transmission capacity variable, bigtriangleupvarphi^max_l. Note that fixed O\\&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.\n\nIn summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions: (1) where and how to invest on capacity, (2) how to dispatch or operate that capacity, (3) which consumer demand segments to serve or curtail, (4) how to cycle and commit thermal units subject to unit commitment decisions, (5) and where and how to invest in additional transmission network capacity to increase power transfer capacity between zones. Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.\n\nPower Balance\n\nThe power balance constraint of the model ensures that electricity demand is met at every time step in each zone. As shown in the constraint, electricity demand, D_tz, at each time step and for each zone must be strictly equal to the sum of generation, Theta_yzt, from thermal technologies (mathcalH), curtailable VRE (mathcalVRE), must-run resources (mathcalMR), and hydro resources (mathcalW). At the same time, energy storage devices (mathcalO) can discharge energy, Theta_yzt to help satisfy demand, while when these devices are charging, Pi_yzt, they increase demand. For the case of flexible demand resources (mathcalDF), delaying demand (equivalent to charging virtual storage), Pi_yzt, decreases demand while satisfying delayed demand (equivalent to discharging virtual demand), Theta_yzt, increases demand. Price-responsive demand curtailment, Lambda_szt, also reduces demand. Finally, power flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign in the below constraint. At the same time losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see Transmission section).\n\nbeginaligned\n\t sum_yin mathcalHTheta_yzt +sum_yin mathcalVRETheta_yzt +sum_yin mathcalMRTheta_yzt + sum_yin mathcalO(Theta_yzt-Pi_yzt) + notag\n\t sum_yin mathcalDF(-Theta_yzt+Pi_yzt) +sum_yin mathcalWTheta_yzt+ notag\n\t+ sum_sin mathcalSLambda_szt - sum_lin mathcalL(varphi^map_lz times Phi_lt) -frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot)) = D_zt\n\tforall zin mathcalZ t in mathcalT\nendaligned\n\nArguments\n\nsetup::Dict: Dictionary containing the settings for the model.\ninputs::Dict: Dictionary containing the inputs for the model.\nOPTIMIZER::MOI.OptimizerWithAttributes: The optimizer to use for solving the model.\n\nReturns\n\nModel: The model object containing the entire optimization problem model to be solved by solve_model.jl\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.solve_model","page":"Public API","title":"GenX.solve_model","text":"solve_model(EP::Model, setup::Dict)\n\nDescription: Solves and extracts solution variables for later processing\n\nArguments\n\nEP::Model: a JuMP model representing the energy optimization problem\nsetup::Dict: a Dict containing GenX setup flags\n\nReturns\n\nEP::Model: the solved JuMP model\nsolver_time::Float64: time taken to solve the model\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.write_outputs","page":"Public API","title":"GenX.write_outputs","text":"write_outputs(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nFunction for the entry-point for writing the different output files. From here, onward several other functions are called, each for writing specific output files, like costs, capacities, etc.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.mga","page":"Public API","title":"GenX.mga","text":"mga(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nWe have implemented an updated Modeling to Generate Alternatives (MGA) Algorithm proposed by Berntsen and Trutnevyte (2017) to generate a set of feasible, near cost-optimal technology portfolios. This algorithm was developed by Brill Jr, E. D., 1979 and introduced to energy system planning by DeCarolia, J. F., 2011.\n\nTo create the MGA formulation, we replace the cost-minimizing objective function of GenX with a new objective function that creates multiple generation portfolios by zone. We further add a new budget constraint based on the optimal objective function value f^* of the least-cost model and the user-specified value of slack delta. After adding the slack constraint, the resulting MGA formulation is given as:\n\nbeginaligned\n\ttextmaxmin quad\n\tsum_z in mathcalZsum_r in mathcalR beta_zr^kP_zr\n\ttextst quad\n\tP_zr = sum_y in mathcalGsum_t in mathcalT omega_t Theta_ytzr \n\t f leq f^* + delta \n\tAx = b\nendaligned\n\nwhere, beta_zr is a random objective fucntion coefficient betwen 0100 for MGA iteration k. Theta_ytzr is a generation of technology y in zone z in time period t that belongs to a resource type r. We aggregate Theta_ytzr into a new variable P_zr that represents total generation from technology type r in a zone z. In the second constraint above, delta denote the increase in budget from the least-cost solution and f represents the expression for the total system cost. The constraint Ax = b represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#Multi-stage-specific-functions","page":"Public API","title":"Multi-stage specific functions","text":"","category":"section"},{"location":"Public_API/public_api/","page":"Public API","title":"Public API","text":"GenX.configure_multi_stage_inputs\nGenX.run_ddp\nGenX.write_multi_stage_outputs","category":"page"},{"location":"Public_API/public_api/#GenX.configure_multi_stage_inputs","page":"Public API","title":"GenX.configure_multi_stage_inputs","text":"function configure_multi_stage_inputs(inputs_d::Dict, settings_d::Dict, NetworkExpansion::Int64)\n\nThis function overwrites input parameters read in via the load_inputs() method for proper configuration of multi-stage modeling:\n\nOvernight capital costs are computed via the compute_overnight_capital_cost() method and overwrite internal model representations of annualized investment costs.\nAnnualized fixed O&M costs are scaled up to represent total fixed O&M incured over the length of each model stage (specified by \"StageLength\" field in multi_stage_settings.yml).\nInternal set representations of resources eligible for capacity retirements are overwritten to ensure compatability with multi-stage modeling.\nWhen NetworkExpansion is active and there are multiple model zones, parameters related to transmission and network expansion are updated. First, annualized transmission reinforcement costs are converted into overnight capital costs. Next, the maximum allowable transmission line reinforcement parameter is overwritten by the model stage-specific value specified in the \"Line_Max_Flow_Possible_MW\" fields in the network_multi_stage.csv file. Finally, internal representations of lines eligible or not eligible for transmission expansion are overwritten based on the updated maximum allowable transmission line reinforcement parameters.\n\ninputs:\n\ninputs_d - dict object containing model inputs dictionary generated by load_inputs().\nsettings_d - dict object containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\nNetworkExpansion - integer flag (0/1) indicating whether network expansion is on, set via the \"NetworkExpansion\" field in genx_settings.yml.\n\nreturns: dictionary containing updated model inputs, to be used in the generate_model() method.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.run_ddp","page":"Public API","title":"GenX.run_ddp","text":"run_ddp(models_d::Dict, setup::Dict, inputs_d::Dict)\n\nThis function run the dual dynamic programming (DDP) algorithm, as described in Pereira and Pinto (1991), and more recently, Lara et al. (2018). Note that if the algorithm does not converge within 10,000 (currently hardcoded) iterations, this function will return models with sub-optimal solutions. However, results will still be printed as if the model is finished solving. This sub-optimal termination is noted in the output with the 'Exiting Without Covergence!' message.\n\ninputs:\n\nmodels_d – Dictionary which contains a JuMP model for each model period.\nsetup - Dictionary object containing GenX settings and key parameters.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method.\n\nreturns:\n\nmodels_d – Dictionary which contains a JuMP model for each model stage, modified by this method.\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\ninputs_d – Dictionary of inputs for each model stage, generated by the load_inputs() method, modified by this method.\n\n\n\n\n\n","category":"function"},{"location":"Public_API/public_api/#GenX.write_multi_stage_outputs","page":"Public API","title":"GenX.write_multi_stage_outputs","text":"write_multi_stage_outputs(stats_d::Dict, outpath::String, settings_d::Dict)\n\nThis function calls various methods which write multi-stage modeling outputs as .csv files.\n\ninputs:\n\nstats_d – Dictionary which contains the run time, upper bound, and lower bound of each DDP iteration.\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings configured in the GenX settings genx_settings.yml file as well as the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"function"},{"location":"Model_Concept_Overview/power_balance/#Power-Balance","page":"Power Balance","title":"Power Balance","text":"","category":"section"},{"location":"Model_Concept_Overview/power_balance/","page":"Power Balance","title":"Power Balance","text":"The power balance constraint of the model ensures that electricity demand is met at every time step in each zone. As shown in the constraint, electricity demand, D_tz, at each time step and for each zone must be strictly equal to the sum of generation, Theta_yzt, from thermal technologies (mathcalH), curtailable variable renewable energy resources (mathcalVRE), must-run resources (mathcalMR), and hydro resources (mathcalW). At the same time, energy storage devices (mathcalO) can discharge energy, Theta_yzt to help satisfy demand, while when these devices are charging, Pi_yzt, they increase demand. Similarly, co-located variable renewable energy and storage resources (mathcalVS and mathcalVS^stor to represent co-located resources with a storage component) can generate electricity from the solar PV and/or wind component and discharge electricity from the storage resource, Theta_yzt to help satisfy demand, and charge from the grid, Pi_yzt, if the storage component of the resource exists. (For the case of flexible demand resources (mathcalDF), delaying demand, Pi_yzt, decreases demand while satisfying delayed demand, Theta_yzt, increases demand.) Price-responsive demand curtailment, Lambda_szt, also reduces demand. Finally, power flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign in the below constraint. At the same time losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see Transmission).","category":"page"},{"location":"Model_Concept_Overview/power_balance/","page":"Power Balance","title":"Power Balance","text":"beginaligned\n\tsum_yin mathcalHTheta_yzt +sum_yin mathcalVRETheta_yzt +sum_yin mathcalMRTheta_yzt + sum_yin mathcalO(Theta_yzt-Pi_yzt) + \n\t sum_yin mathcalDF(-Theta_yzt+Pi_yzt) +sum_yin mathcalWTheta_yzt+ sum_yin mathcalVSTheta_yzt - sum_yin mathcalVS^storPi_yzt + \n\t sum_sin mathcalSLambda_szt - sum_lin mathcalL(varphi^map_lz times Phi_lt) -frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot)) = D_zt\n\tquad quad forall zin mathcalZ t in mathcalT\nendaligned","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"\n","category":"page"},{"location":"#Welcome-to-the-GenX-documentation!","page":"GenX: Introduction","title":"Welcome to the GenX documentation!","text":"","category":"section"},{"location":"#What-is-GenX?","page":"GenX: Introduction","title":"What is GenX?","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX is a highly-configurable, open source electricity resource capacity expansion model that incorporates several state-of-the-art practices in electricity system planning to offer improved decision support for a changing electricity landscape.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The model was originally developed by Jesse D. Jenkins and Nestor A. Sepulveda at the Massachusetts Institute of Technology and is now jointly maintained by a team of contributors at the Princeton University ZERO Lab (led by Jenkins), MIT (led by Ruaridh MacDonald), and NYU (led by Dharik Mallapragada). ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX is a constrained linear or mixed integer linear optimization model that determines the portfolio of electricity generation, storage, transmission, and demand-side resource investments and operational decisions to meet electricity demand in one or more future planning years at lowest cost, while subject to a variety of power system operational constraints, resource availability limits, and other imposed environmental, market design, and policy constraints.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX features a modular and transparent code structure developed in Julia + JuMP. The model is designed to be highly flexible and configurable for use in a variety of applications from academic research and technology evaluation to public policy and regulatory analysis and resource planning. See the User Guide for more information on how to use GenX and the Developer Guide for more information on how to contribute to GenX.","category":"page"},{"location":"#Uses","page":"GenX: Introduction","title":"Uses","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.","category":"page"},{"location":"#Roadmap-of-the-Documentation:-A-Guide-for-the-Users-and-Developers","page":"GenX: Introduction","title":"Roadmap of the Documentation: A Guide for the Users and Developers","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"This section provides a quick guidance as to how to navigate through the different parts of the documentation pages; what the different sections contain, and how to relate it to the different parts of the GenX code-base. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"This page serves as a gentle introduction to what GenX is meant for and what it does. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The next subsection, Installation Guide goes over how to download and install GenX and also how to download and install the Julia programming language (in which GenX is written) and the different open-source non-commercial freely available solvers, as well as the commercial solvers and the respective JuMP interfaces. This subsection also goes over installing the environment dependencies and instantiating a virtual environment.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"We also mention the shortcomings of GenX and some third party extentions in the next couple subsections","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The next section is Getting Started goes over Running GenX and has two subsections. The first subsection, Example cases, gives a walkthrough through some predefined example systems and how to run GenX for those and interpret the results. It also tells how to run GenX for a user-defined case. The subsection Using commercial solvers: Gurobi or CPLEX talks specifically about how to run GenX with commercial solvers like Gurobi and CPLEX that are absolutely indispensable for solving large cases. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The third section, Tutorial starts with GenX Tutorials and gives a comprehensive tour of the different steps that are involved when a GenX capacity expansion simulation is run. It consists of 6 tutorial sections, each of which highlights the different important aspects of model construction and run of GenX. The different sections are configuring the GenX settings, visualizing the network, time domain reduction, generating the model, solving the model, and adjusting the different solver settings.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The User Guide, which the fourth section (User Guide) goes into the depths and details of the different steps and the settings and input parameters from the previous Tutorial section. The sections starts off with an overview of the workflow in GenX, briefing about the different steps (some of which we encountered in the Tutorials) of running GenX model. It then explains the different parameters of settings, policy, time-domain reduction, model structure, and output. Following this, the next subsection explains the different solver settings parameters of the different solvers. The next subsection goes over the different input CSV files and the different fields that are used there. The following two subsections are devoted to Time Domain Reduction (TDR). The first one walks through and explains the different settings parameters for TDR and the second one explains the couple different ways to run TDR for GenX and what exactly happens when we run TDR. The next four subsections, respectively, explains the different parameters, inputs, and outputs, and what happens when Modeling to Generate Alternatives (MGA), Multi-stage model, slack variables for policies (when we want to satisfy policy constraints in a soft manner by adding penalty of violation in the objective function), and Method of Morris. Finally, the last two sections are about the different steps involved while solving the model and the explanation of different output fields for both the default settings and user-specific settings. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The Model Concept and Overview section first introduces the GenX model in GenX Model Introduction and talks about its scope. It also introduces the notations, the objective function, and the power balance constraints. This is the first section which delves into the theoretical and mathematical details of the model, which is the most important one for model developers.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The Model Reference, which is the sixth section delves deep into the GenX model and introduces the mathematical formulation, while discussing the physical interpretations of all the different parts of the GenX model. This section starts off with discussing the Core of the model, which models the Discharge, Non-Served Energy, Operational Reserves, Transmission, Unit Commitment, CO2, and Fuel. The different parts of the model consists of the different tyoe of generating resources (thermal, hydro, VRE, storage etc.), transmission network (modeling of flows as well as losses), demand modeling, operating reserves, unit commitment, different policies (such as CO2 constraint, capacity reserve margin, energy share requirement, min and max cap requirement etc.). This section also mentions about the different Julia functions (or methods) used for loading the input files, building the model, solving it, and generating the output files. Also, this is the section that explains the internal details of the Julia functions used for TDR, MGA, Method of Morris, Multi-stage modeling, and the several utility functions used throughout the GenX code-base. ","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The seventh section, Public API Reference Public Documentation is for describing the functions that are directly accessible to an external program from GenX (like loading inputs, generating output, running TDR script etc.) and how an external \"client\" code can access the GenX features, if the user desires to run his/her own code instead of the Run.jl provided by us.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The eighth section, Third Party Extension Additional Third Party Extensions to GenX mentions about Pygenx, a Python interface for GenX, that was built by Daniel Olsen and GenX case runner for automated batch running, built by Jacob Schwartz.","category":"page"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"Finally, the ninth and last section, Developer Docs How to contribute to GenX talks about the resource organization in GenX, how to add a new user-defined resource, and also several JuMP functions that are used as utility throughout the GenX code-base. ","category":"page"},{"location":"#How-to-cite-GenX","page":"GenX: Introduction","title":"How to cite GenX","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"We recommend users of GenX to cite it in their academic publications and patent filings. Here's the text to put up as the citation for GenX: MIT Energy Initiative and Princeton University ZERO lab. [GenX](https://github.com/GenXProject/GenX): a configurable power system capacity expansion model for studying low-carbon energy futures n.d. https://github.com/GenXProject/GenX.","category":"page"},{"location":"#Acknowledgement","page":"GenX: Introduction","title":"Acknowledgement","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"The GenX team expresses deep gratitude to Laura Zwanziger and Jacob Schwartz for designing the Julia-themed GenX logo and to Maya Mutic for developing the tutorials along with Filippo Pecci and Luca Bonaldo. ","category":"page"},{"location":"#License","page":"GenX: Introduction","title":"License","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"GenX is released under the General Public License, GPL-2.0","category":"page"},{"location":"#Index","page":"GenX: Introduction","title":"Index","text":"","category":"section"},{"location":"","page":"GenX: Introduction","title":"GenX: Introduction","text":"Pages = [\"Model_Reference/core.md\",\n \"Model_Reference/Resources/curtailable_variable_renewable.md\",\n \"Model_Reference/Resources/flexible_demand.md\",\n \"Model_Reference/Resources/hydro_res.md\",\n \"Model_Reference/Resources/hydro_inter_period_linkage.md\",\n \"Model_Reference/Resources/must_run.md\",\n \"Model_Reference/Resources/storage.md\",\n \"Model_Reference/Resources/investment_charge.md\",\n \"Model_Reference/Resources/investment_energy.md\",\n \"Model_Reference/Resources/long_duration_storage.md\",\n \"Model_Reference/Resources/storage_all.md\",\n \"Model_Reference/Resources/storage_asymmetric.md\",\n \"Model_Reference/Resources/storage_symmetric.md\",\n \"Model_Reference/Resources/vre_stor.md\",\n \"Model_Reference/Resources/thermal.md\",\n \"Model_Reference/Resources/thermal_commit.md\",\n \"Model_Reference/Resources/thermal_no_commit.md\",\n \"Model_Reference/Resources/electrolyzers.md\",\n \"Model_Reference/Resources/maintenance.md\",\n \"Model_Reference/policies.md\",\n \"User_Guide/solver_configuration.md\",\n \"Model_Reference/load_inputs.md\",\n \"Model_Reference/TDR.md\",\n \"Model_Reference/Multi_Stage/configure_multi_stage_inputs.md\",\n \"Model_Reference/Multi_Stage/dual_dynamic_programming.md\",\n \"Public_API/solve_model.md\",\n \"Public_API/mga.md\",\n \"Public_API/methodofmorris.md\",\n \"Public_API/write_outputs.md\"]","category":"page"},{"location":"Model_Reference/Resources/hydro_res/#Hydro-Resources","page":"Hydro Reservoir","title":"Hydro Resources","text":"","category":"section"},{"location":"Model_Reference/Resources/hydro_res/","page":"Hydro Reservoir","title":"Hydro Reservoir","text":"Modules = [GenX]\nPages = [\"hydro_res.jl\"]","category":"page"},{"location":"Model_Reference/Resources/hydro_res/#GenX.hydro_res!-Tuple{JuMP.Model, Dict, Dict}","page":"Hydro Reservoir","title":"GenX.hydro_res!","text":"hydro_res!(EP::Model, inputs::Dict, setup::Dict)\n\nThis module defines the operational constraints for reservoir hydropower plants. Hydroelectric generators with water storage reservoirs (y in mathcalW) are effectively modeled as energy storage devices that cannot charge from the grid and instead receive exogenous inflows to their storage reservoirs, reflecting stream flow inputs. For resources with unknown reservoir capacity (y in mathcalW^nocap), their operation is parametrized by their generation efficiency, eta_yz^down, and energy inflows to the reservoir at every time-step, represented as a fraction of the total power capacity,(rho^max_yzt). In case reservoir capacity is known (y in mathcalW^cap), an additional parameter, mu^stor_yz, referring to the ratio of energy capacity to discharge power capacity, is used to define the available reservoir storage capacity.\n\nStorage inventory balance Reservoir hydro systems are governed by the storage inventory balance constraint given below. This constraint enforces that energy level of the reservoir resource y and zone z in time step t (Gamma_yzt) is defined as the sum of the reservoir level in the previous time step, less the amount of electricity generated, Theta_yzt (accounting for the generation efficiency, eta_yz^down), minus any spillage varrho_yzt, plus the hourly inflows into the reservoir (equal to the installed reservoir discharged capacity times the normalized hourly inflow parameter rho^max_yz t).\n\nbeginaligned\nGamma_yzt = Gamma_yzt-1 -frac1eta_yz^downTheta_yzt - varrho_yzt + rho^max_yzt times Delta^total_yz hspace1 cm forall y in mathcalW z in mathcalZ t in mathcalT^interior \nGamma_yzt = Gamma_yzt+tau^period-1 -frac1eta_yz^downTheta_yzt - varrho_yzt + rho^max_yzt times Delta^total_yz hspace1 cm forall y in mathcalW z in mathcalZ t in mathcalT^start\nendaligned\n\nWe implement time-wrapping to endogenize the definition of the intial state prior to the first period with the following assumption. If time step t is the first time step of the year then storage inventory at t is defined based on last time step of the year. Alternatively, if time step t is the first time step of a representative period, then storage inventory at t is defined based on the last time step of the representative period. Thus, when using representative periods, the storage balance constraint for hydro resources does not allow for energy exchange between representative periods. Note: in future updates, an option to model hydro resources with large reservoirs that can transfer energy across sample periods will be implemented, similar to the functions for modeling long duration energy storage in long_duration_storage.jl.\n\nRamping Limits The following constraints enforce hourly changes in power output (ramps down and ramps up) to be less than the maximum ramp rates (kappa^down_yz and kappa^up_yz ) in per unit terms times the total installed capacity of technology y (Delta^total_yz).\n\nbeginaligned\nTheta_yzt + f_yzt + r_yzt - Theta_yzt-1 - f_yzt-1 leq kappa^up_yz times Delta^total_yz\nhspace2 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nbeginaligned\nTheta_yzt-1 + f_yzt-1 + r_yzt-1 - Theta_yzt - f_yztleq kappa^down_yz Delta^total_yz\nhspace2 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nRamping constraints are enforced for all time steps except the first time step of the year or first time of each representative period when using representative periods to model grid operations.\n\nPower generation and stream flow bounds Electricity production plus total spilled power from hydro resources is constrained to always be above a minimum output parameter, rho^min_yz, to represent operational constraints related to minimum stream flows or other demands for water from hydro reservoirs. Electricity production is constrained by either the the net installed capacity or by the energy level in the reservoir in the prior time step, whichever is more binding. For the latter constraint, the constraint for the first time step of the year (or the first time step of each representative period) is implemented based on energy storage level in last time step of the year (or last time step of each representative period).\n\nbeginaligned\nTheta_yzt + varrho_yzt geq rho^min_yz times Delta^total_yz\nhspace2 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nbeginaligned\nTheta_yt leq times Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ tin mathcalT\nendaligned\n\nbeginaligned\nTheta_yzt leq Gamma_yt-1\nhspace4 cm forall y in mathcalW z in mathcalZ tin mathcalT\nendaligned\n\nReservoir energy capacity constraint In case the reservoir capacity is known (y in W^cap), then an additional constraint enforces the total stored energy in each time step to be less than or equal to the available reservoir capacity. Here, the reservoir capacity is defined multiplying the parameter, mu^stor_yz with the available power capacity.\n\nbeginaligned\nGamma_yz t leq mu^stor_yztimes Delta^total_yz\nhspace4 cm forall y in mathcalW^cap z in mathcalZ tin mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/hydro_res/#GenX.hydro_res_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Hydro Reservoir","title":"GenX.hydro_res_operational_reserves!","text":"hydro_res_operational_reserves!(EP::Model, inputs::Dict)\n\nThis module defines the modified constraints and additional constraints needed when modeling operating reserves\n\nModifications when operating reserves are modeled When modeling operating reserves, the constraints regarding maximum power flow limits are modified to account for procuring some of the available capacity for frequency regulation (f_yzt) and \"updward\" operating (or spinning) reserves (r_yzt).\n\nbeginaligned\n Theta_yzt + f_yzt +r_yzt leq times Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ tin mathcalT\nendaligned\n\nThe amount of downward frequency regulation reserves cannot exceed the current power output.\n\nbeginaligned\n f_yzt leq Theta_yzt\nhspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\nThe amount of frequency regulation and operating reserves procured in each time step is bounded by the user-specified fraction (upsilon^reg_yz,upsilon^rsv_yz) of nameplate capacity for each reserve type, reflecting the maximum ramp rate for the hydro resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nbeginaligned\nf_yzt leq upsilon^reg_yz times Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT \nr_yz t leq upsilon^rsv_yztimes Delta^total_yz\nhspace4 cm forall y in mathcalW z in mathcalZ t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/maintenance/#Optimized-Scheduled-Maintenance","page":"Scheduled maintenance for various resources","title":"Optimized Scheduled Maintenance","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Added in v0.4","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"In the real world, some types of resources (notably, fission) require regular scheduled maintenance, which often takes several weeks. During this time, the plant produces no power. This module allows GenX to find the best time of year for plants to undergo maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Scheduled maintenance is implemented only for thermal plants with unit commitment (THERM=1).","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Description-of-the-maintenance-model","page":"Scheduled maintenance for various resources","title":"Description of the maintenance model","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"A plant requires a single contiguous period of h ge 1 hours of maintenance, every y ge 1 years. For each plant, the best time to start the maintenance period is determined by the optimizer.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"During maintenance, the plant cannot be \"commited\", and therefore","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"uses no fuel,\nproduces no power,\nand does not contribute to reserves.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Additionally, ","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"the plant does not contribute to any Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Treatment-of-plants-that-require-maintenance-only-every-few-years","page":"Scheduled maintenance for various resources","title":"Treatment of plants that require maintenance only every few years","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"GenX models a long-term equilibrium, and each problem generally represents a single full year. If a plant requires maintenance every y years, we take the simplification that at least 1y of the plants must undergo maintenance in the modeled year.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"See also \"Interaction with integer unit commitment\" below.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Reduction-of-number-of-possible-start-dates","page":"Scheduled maintenance for various resources","title":"Reduction of number of possible start dates","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"This module creates constraints which work across long periods, and consequently can be very expensive to solve. In order to reduce the expense, the set of possible maintenance start dates can be limited. Rather than have maintenance potentially start every hour, one can have possible start dates which are once per day, once per week, etc. (In reality, maintenance is likely scheduled months in advance, so optimizing down to the hour may not be realistic anyway.)","category":"page"},{"location":"Model_Reference/Resources/maintenance/#How-to-use","page":"Scheduled maintenance for various resources","title":"How to use","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"There are four columns which need to be added to the plant data, i.e. in the resource .csv files:","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"MAINT should be 1 for plants that require maintenance and 0 otherwise.\nMaintenance_Duration is the number of hours the maintenance period lasts.\nMaintenance_Cycle_Length_Years. If 1, maintenance every year, if 3 maintenance every 3 years, etc.\nMaintenance_Begin_Cadence. Spacing between hours in which maintenance can start.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The last three fields must be integers which are greater than 0. They are ignored for any plants which do not require maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Maintenance_Duration must be less than the total number of hours in the year.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If Maintenance_Begin_Cadence is 1 then the maintenance can begin in any hour. If it is 168 then it can begin in hours 1, 169, 337, etc.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Restrictions-on-use","page":"Scheduled maintenance for various resources","title":"Restrictions on use","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The maintenance module has these restrictions:","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"More than a single maintenance period per year (i.e. every three months) is not possible in the current formulation.\nOnly full-year cases can be run; there must be only one \"representative period\".","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"It would not make sense to model a month-long maintenance period when the year is modeled as a series of representative weeks, for example.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Interaction-with-integer-unit-commitment","page":"Scheduled maintenance for various resources","title":"Interaction with integer unit commitment","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If integer unit commitment is on (UCommit=1) this module may not produce correct results; there may be more maintenance than the user wants. This is because the formulation specifies that the number of plants that go down for maintenance in the simulated year must be at least (the number of plants in the zone)/(the maintenance cycle length in years). As a reminder, the number of plants is eTotalCap / Cap_Size.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If there were three 500 MW plants (total 1500 MW) in a zone, and they require maintenance every three years (Maintenance_Cycle_Length_Years=3), the formulation will work properly: one of the three plants will go under maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"But if there was only one 500 MW plant, and it requires maintenance every 3 years, the constraint will still make it do maintenance every year, because ceil(1/3) is 1. The whole 500 MW plant will do maintenance. This is the unexpected behavior.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"However, if integer unit commitment was relaxed to \"linearized\" unit commitment (UCommit=2), the model will have only 500 MW / 3 = 166.6 MW worth of this plant do maintenance.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Hint:-pre-scheduling-maintenance","page":"Scheduled maintenance for various resources","title":"Hint: pre-scheduling maintenance","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If you want to pre-schedule when maintenance occurs, you might not need this module. Instead, you could set the maximum power output of the plant to zero for a certain period, or make its fuel extremely expensive during that time. However, the plant would still be able to contribute to the Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Outputs-produced","page":"Scheduled maintenance for various resources","title":"Outputs produced","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"If at least one plant has MAINT=1, a file maint_down.csv will be written listing how many plants are down for maintenance in each timestep.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Notes-on-mathematical-formulation","page":"Scheduled maintenance for various resources","title":"Notes on mathematical formulation","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The formulation of the maintenance state is very similar to the formulation of unit commitment.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"There is a variable called something like vMSHUT which is analogous to vSTART and controls the start of the maintenance period. There is another variable called something like vMDOWN analogous to vCOMMIT which controls the maintenance status in any hour.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"A constraint ensures that the value of vMDOWN in any hour is always more than the number of vMSHUTs in the previous Maintenance_Duration hours.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"Another constraint ensures that the number of plants committed (vCOMMIT) at any one time plus the number of plants under maintenance (vMDOWN) is less than the total number of plants.","category":"page"},{"location":"Model_Reference/Resources/maintenance/#Developer-note:-adding-maintenance-to-a-resource","page":"Scheduled maintenance for various resources","title":"Developer note: adding maintenance to a resource","text":"","category":"section"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"The maintenance formulation is applied on a per-resource basis, by calling the function maintenance_formulation!.","category":"page"},{"location":"Model_Reference/Resources/maintenance/","page":"Scheduled maintenance for various resources","title":"Scheduled maintenance for various resources","text":"GenX.maintenance_formulation!\nGenX.resources_with_maintenance\nGenX.maintenance_down_name\nGenX.maintenance_shut_name\nGenX.controlling_maintenance_start_hours\nGenX.ensure_maintenance_variable_records!\nGenX.has_maintenance\nGenX.maintenance_down_variables","category":"page"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_formulation!","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_formulation!","text":"maintenance_formulation!(EP::Model,\n inputs::Dict,\n resource_component::AbstractString,\n r_id::Int,\n maint_begin_cadence::Int,\n maint_dur::Int,\n maint_freq_years::Int,\n cap::Float64,\n vcommit::Symbol,\n ecap::Symbol,\n integer_operational_unit_commitment::Bool)\n\nEP: the JuMP model\ninputs: main data storage\nresource_component: unique resource name with optional component name\n If the plant has more than one component, this could identify a specific part which\n is undergoing maintenance.\nr_id: Resource ID (unique resource integer)\nmaint_begin_cadence:\n It may be too expensive (from an optimization perspective) to allow maintenance\n to begin at any time step during the simulation. Instead this integer describes\n the cadence of timesteps in which maintenance can begin. Must be at least 1.\nmaint_dur: Number of timesteps that maintenance takes. Must be at least 1.\nmaint_freq_years: 1 is maintenannce every year,\n 2 is maintenance every other year, etc. Must be at least 1.\ncap: Plant electrical capacity.\nvcommit: Symbol of vCOMMIT-like variable.\necap: Symbol of eTotalCap-like variable.\ninteger_operational_unit_commitment: whether this plant has integer unit\n commitment for operational variables.\n\nCreates maintenance-tracking variables and adds their Symbols to two Sets in `inputs`.\nAdds constraints which act on the vCOMMIT-like variable.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.resources_with_maintenance","page":"Scheduled maintenance for various resources","title":"GenX.resources_with_maintenance","text":"resources_with_maintenance(df::DataFrame)::Vector{Int}\n\nGet a vector of the R_ID's of all resources listed in a dataframe\nthat have maintenance requirements. If there are none, return an empty vector.\n\nThis method takes a specific dataframe because compound resources may have their\ndata in multiple dataframes.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_down_name","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_down_name","text":"maintenance_down_name(resource_component::AbstractString)::String\n\nJuMP variable name to control whether a resource-component is down for maintenance.\nHere resource-component could be a whole resource or a component (for complex resources).\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_shut_name","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_shut_name","text":"maintenance_shut_name(resource_component::AbstractString)::String\n\nJuMP variable name to control when a resource-components begins maintenance.\nHere resource-component could be a whole resource or a component (for complex resources).\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.controlling_maintenance_start_hours","page":"Scheduled maintenance for various resources","title":"GenX.controlling_maintenance_start_hours","text":"controlling_maintenance_start_hours(p::Int, t::Int, maintenance_duration::Int, maintenance_begin_hours::UnitRange{Int64})\n\np: hours_per_subperiod\nt: the current hour\nmaintenance_duration: length of a maintenance period\nmaintenance_begin_hours: collection of hours in which maintenance is allowed to start\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.ensure_maintenance_variable_records!","page":"Scheduled maintenance for various resources","title":"GenX.ensure_maintenance_variable_records!","text":"ensure_maintenance_variable_records!(dict::Dict)\n\ndict: a dictionary of model data\n\nThis should be called by each method that adds maintenance formulations,\nto ensure that certain entries in the model data dict exist.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.has_maintenance","page":"Scheduled maintenance for various resources","title":"GenX.has_maintenance","text":"has_maintenance(dict::Dict)\n\ndict: a dictionary of model data\n\nChecks whether the dictionary contains listings of maintenance-related variable names.\nThis is true only after `maintenance_formulation!` has been called.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/maintenance/#GenX.maintenance_down_variables","page":"Scheduled maintenance for various resources","title":"GenX.maintenance_down_variables","text":"maintenance_down_variables(dict::Dict)\n\ndict: a dictionary of model data\n\nget listings of maintenance-related variable names.\nThis is available only after `maintenance_formulation!` has been called.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/#Endogenous-Retirement","page":"Endogenous Retirement","title":"Endogenous Retirement","text":"","category":"section"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/","page":"Endogenous Retirement","title":"Endogenous Retirement","text":"Modules = [GenX]\nPages = [\"endogenous_retirement.jl\"]","category":"page"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/#GenX.endogenous_retirement_discharge!-Tuple{JuMP.Model, Dict, Int64, Int64, Vector{Int64}}","page":"Endogenous Retirement","title":"GenX.endogenous_retirement_discharge!","text":"endogenous_retirement_discharge!(EP::Model, inputs::Dict, num_stages::Int, cur_stage::Int, stage_lens::Array{Int, 1})\n\nThis function models the following constraint\n\nbeginaligned\n RETCAP_yp geq sum^p_t=1 MINRET_yt + sum^r_t=1CAP_yt - sum^p_t=1RETCAP_yp\nendaligned\n\nwhere r in 1 (p-1) is defined as the last stage such that if we built y at the end of stage r, it would reach its end of life before the end of stage p. In other words, it is the largest index r in 1 (p-1) such that:\n\nbeginaligned\nsum^p_t=r+1StageLength_t leq LifeTime_y\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Multi_Stage/endogenous_retirement/#GenX.get_retirement_stage-Tuple{Int64, Int64, Vector{Int64}}","page":"Endogenous Retirement","title":"GenX.get_retirement_stage","text":"get_retirement_stage(cur_stage::Int, stage_len::Int, lifetime::Int, stage_lens::Array{Int, 1})\n\nThis function determines the model stage before which all newly built capacity must be retired. Used to enforce endogenous lifetime retirements in multi-stage modeling.\n\ninputs:\n\ncur_stage – An Int representing the current model stage p.\nlifetime – An Int representing the lifetime of a particular resource.\nstage_lens – An Int array representing the length L of each model stage.\n\nreturns: An Int representing the model stage in before which the resource must retire due to endogenous lifetime retirements.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#Utility-Functions","page":"Utility Functions","title":"Utility Functions","text":"","category":"section"},{"location":"Model_Reference/utility_functions/","page":"Utility Functions","title":"Utility Functions","text":"Modules = [GenX]\nPages = [\"utility.jl\"]","category":"page"},{"location":"Model_Reference/utility_functions/#GenX.by_rid_res-Tuple{Integer, Symbol, Vector{<:GenX.AbstractResource}}","page":"Utility Functions","title":"GenX.by_rid_res","text":"by_rid_res(rid::Integer, sym::Symbol, rs::Vector{<:AbstractResource})\n\nThis function returns the value of the attribute `sym` for the resource given by the ID `rid`.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursafter-Tuple{Int64, Int64, Int64}","page":"Utility Functions","title":"GenX.hoursafter","text":"hoursafter(p::Int, t::Int, a::Int)\n\nDetermines the time index a hours after index t in a landscape starting from t=1 which is separated into distinct periods of length p.\n\nFor example, if p = 10, 1 hour after t=9 is t=10, 1 hour after t=10 is t=1, 1 hour after t=11 is t=2\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursafter-Tuple{Int64, Int64, UnitRange{Int64}}","page":"Utility Functions","title":"GenX.hoursafter","text":"hoursafter(p::Int, t::Int, b::UnitRange)\n\nThis is a generalization of hoursafter(... b::Int) to allow for example a=1:3 to fetch a Vector{Int} of the three hours after time index t.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursbefore-Tuple{Int64, Int64, Int64}","page":"Utility Functions","title":"GenX.hoursbefore","text":"hoursbefore(p::Int, t::Int, b::Int)\n\nDetermines the time index b hours before index t in a landscape starting from t=1 which is separated into distinct periods of length p.\n\nFor example, if p = 10, 1 hour before t=1 is t=10, 1 hour before t=10 is t=9 1 hour before t=11 is t=20\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.hoursbefore-Tuple{Int64, Int64, UnitRange{Int64}}","page":"Utility Functions","title":"GenX.hoursbefore","text":"hoursbefore(p::Int, t::Int, b::UnitRange)\n\nThis is a generalization of hoursbefore(... b::Int) to allow for example b=1:3 to fetch a Vector{Int} of the three hours before time index t.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/utility_functions/#GenX.is_nonzero-Tuple{DataFrames.DataFrame, Symbol}","page":"Utility Functions","title":"GenX.is_nonzero","text":"is_nonzero(df::DataFrame, col::Symbol)::BitVector\n\nThis function checks if a column in a dataframe is all zeros.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#Time-Domain-Reduction-(TDR)","page":"Time-domain Reduction","title":"Time Domain Reduction (TDR)","text":"","category":"section"},{"location":"Model_Reference/TDR/","page":"Time-domain Reduction","title":"Time-domain Reduction","text":"Modules = [GenX]\nPages = [\"time_domain_reduction.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"Model_Reference/TDR/#GenX.RemoveConstCols","page":"Time-domain Reduction","title":"GenX.RemoveConstCols","text":"RemoveConstCols(all_profiles, all_col_names)\n\nRemove and store the columns that do not vary during the period.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.check_condition-NTuple{5, Any}","page":"Time-domain Reduction","title":"GenX.check_condition","text":"check_condition(Threshold, R, OldColNames, ScalingMethod, TimestepsPerRepPeriod)\n\nCheck whether the greatest Euclidean deviation in the input data and the clustered representation is within a given proportion of the \"maximum\" possible deviation.\n\n(1 for Normalization covers 100%, 4 for Standardization covers ~95%)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.cluster","page":"Time-domain Reduction","title":"GenX.cluster","text":"cluster(ClusterMethod, ClusteringInputDF, NClusters, nIters, v=false, random=true)\n\nGet representative periods using cluster centers from kmeans or kmedoids.\n\nK-Means: https://juliastats.org/Clustering.jl/dev/kmeans.html\n\nK-Medoids: https://juliastats.org/Clustering.jl/stable/kmedoids.html\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.cluster_inputs","page":"Time-domain Reduction","title":"GenX.cluster_inputs","text":"cluster_inputs(inpath, settings_path, mysetup, stage_id=-99, v=false; random=true)\n\nUse kmeans or kmedoids to cluster raw demand profiles and resource capacity factor profiles into representative periods. Use Extreme Periods to capture noteworthy periods or periods with notably poor fits.\n\nIn Demand_data.csv, include the following:\n\nTimesteps_per_Rep_Period - Typically 168 timesteps (e.g., hours) per period, this designates the length of each representative period.\nUseExtremePeriods - Either 1 or 0, this designates whether or not to include outliers (by performance or demand/resource extreme) as their own representative periods. This setting automatically includes the periods with maximum demand, minimum solar cf and minimum wind cf as extreme periods.\nClusterMethod - Either 'kmeans' or 'kmedoids', this designates the method used to cluster periods and determine each point's representative period.\nScalingMethod - Either 'N' or 'S', this designates directs the module to normalize ([0,1]) or standardize (mean 0, variance 1) the input data.\nMinPeriods - The minimum number of periods used to represent the input data. If using UseExtremePeriods, this must be at least three. If IterativelyAddPeriods if off, this will be the total number of periods.\nMaxPeriods - The maximum number of periods - both clustered periods and extreme periods - that may be used to represent the input data.\nIterativelyAddPeriods - Either 1 or 0, this designates whether or not to add periods until the error threshold between input data and represented data is met or the maximum number of periods is reached.\nThreshold - Iterative period addition will end if the period farthest (Euclidean Distance) from its representative period is within this percentage of the total possible error (for normalization) or ~95% of the total possible error (for standardization). E.g., for a threshold of 0.01, every period must be within 1% of the spread of possible error before the clustering iterations will terminate (or until the max number of periods is reached).\nIterateMethod - Either 'cluster' or 'extreme', this designates whether to add clusters to the kmeans/kmedoids method or to set aside the worst-fitting periods as a new extreme periods.\nnReps - The number of times to repeat each kmeans/kmedoids clustering at the same setting.\nDemandWeight - Default 1, this is an optional multiplier on demand columns in order to prioritize better fits for demand profiles over resource capacity factor profiles.\nWeightTotal - Default 8760, the sum to which the relative weights of representative periods will be scaled.\nClusterFuelPrices - Either 1 or 0, this indicates whether or not to use the fuel price time series in Fuels_data.csv in the clustering process. If 'no', this function will still write Fuels_data_clustered.csv with reshaped fuel prices based on the number and size of the representative weeks, assuming a constant time series of fuel prices with length equal to the number of timesteps in the raw input data.\nMultiStageConcatenate - (Only considered if MultiStage = 1 in genx_settings.yml) If 1, this designates that the model should time domain reduce the input data of all model stages together. Else if 0, [still in development] the model will time domain reduce only the first stage and will apply the periods of each other model stage to this set of representative periods by closest Eucliden distance.\n\nFor co-located VRE-STOR resources, all capacity factors must be in the Generatorsvariability.csv file in addition to separate Vreandstorsolarvariability.csv and Vreandstorwind_variability.csv files. The co-located solar PV and wind profiles for co-located resources will be separated into different CSV files to be read by loading the inputs after the clustering of the inputs has occurred. \n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.get_absolute_extreme-NTuple{4, Any}","page":"Time-domain Reduction","title":"GenX.get_absolute_extreme","text":"get_absolute_extreme(DF, statKey, col_names, ConstCols)\n\nGet the period index of the single timestep with the minimum or maximum demand or capacity factor.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.get_demand_multipliers","page":"Time-domain Reduction","title":"GenX.get_demand_multipliers","text":"get_demand_multipliers(ClusterOutputData, ModifiedData, M, W, DemandCols, TimestepsPerRepPeriod, NewColNames, NClusters, Ncols)\n\nGet multipliers to linearly scale clustered demand profiles L zone-wise such that their weighted sum equals the original zonal total demand. Scale demand profiles later using these multipliers in order to ensure that a copy of the original demand is kept for validation.\n\nFind k_z such that:\n\nsum_i in I L_iz = sum_t in T m in M C_tmz cdot fracw_mT cdot k_z forall z in Z\n\nwhere Z is the set of zones, I is the full time domain, T is the length of one period (e.g., 168 for one week in hours), M is the set of representative periods, L_iz is the original zonal demand profile over time (hour) index i, C_imz is the demand in timestep i for representative period m in zone z, w_m is the weight of the representative period equal to the total number of hours that one hour in representative period m represents in the original profile, and k_z is the zonal demand multiplier returned by the function.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.get_extreme_period","page":"Time-domain Reduction","title":"GenX.get_extreme_period","text":"get_extreme_period(DF, GDF, profKey, typeKey, statKey,\n ConstCols, demand_col_names, solar_col_names, wind_col_names)\n\nIdentify extreme week by specification of profile type (Demand, PV, Wind), measurement type (absolute (timestep with min/max value) vs. integral (period with min/max summed value)), and statistic (minimum or maximum). I.e., the user could want the hour with the most demand across the whole system to be included among the extreme periods. They would select \"Demand\", \"System, \"Absolute, and \"Max\".\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/#GenX.get_integral_extreme-NTuple{4, Any}","page":"Time-domain Reduction","title":"GenX.get_integral_extreme","text":"get_integral_extreme(GDF, statKey, col_names, ConstCols)\n\nGet the period index with the minimum or maximum demand or capacity factor summed over the period.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.get_worst_period_idx-Tuple{Any}","page":"Time-domain Reduction","title":"GenX.get_worst_period_idx","text":"get_worst_period_idx(R)\n\nGet the index of the period that is farthest from its representative period by Euclidean distance.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.parse_data-Tuple{Any}","page":"Time-domain Reduction","title":"GenX.parse_data","text":"parse_data(myinputs)\n\nGet demand, solar, wind, and other curves from the input data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.parse_multi_stage_data-Tuple{Any}","page":"Time-domain Reduction","title":"GenX.parse_multi_stage_data","text":"parse_mutli_period_data(inputs_dict)\n\nGet demand, solar, wind, and other curves from multi-stage input data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.rmse_score-Tuple{Any, Any}","page":"Time-domain Reduction","title":"GenX.rmse_score","text":"rmse_score(y_true, y_pred)\n\nCalculates Root Mean Square Error.\n\nRMSE = sqrtfrac1nSigma_i=1^nBig(fracd_i -f_isigma_iBig)^2\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/TDR/#GenX.scale_weights","page":"Time-domain Reduction","title":"GenX.scale_weights","text":"scale_weights(W, H)\n\nLinearly scale weights W such that they sum to the desired number of timesteps (hours) H.\n\nw_j leftarrow H cdot fracw_jsum_i w_i forall w_j in W\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/TDR/","page":"Time-domain Reduction","title":"Time-domain Reduction","text":"GenX.run_timedomainreduction!","category":"page"},{"location":"Model_Reference/TDR/#GenX.run_timedomainreduction!","page":"Time-domain Reduction","title":"GenX.run_timedomainreduction!","text":"Run the GenX time domain reduction on the given case folder\n\ncase - folder for the case stage_id - possibly something to do with MultiStage verbose - print extra outputs\n\nThis function overwrites the time-domain-reduced inputs if they already exist.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/Resources/flexible_demand/#Flexible-Demand","page":"Flexible Demand","title":"Flexible Demand","text":"","category":"section"},{"location":"Model_Reference/Resources/flexible_demand/","page":"Flexible Demand","title":"Flexible Demand","text":"Modules = [GenX]\nPages = [\"flexible_demand.jl\"]","category":"page"},{"location":"Model_Reference/Resources/flexible_demand/#GenX.flexible_demand!-Tuple{JuMP.Model, Dict, Dict}","page":"Flexible Demand","title":"GenX.flexible_demand!","text":"flexible_demand!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the operating constraints for flexible demand resources. As implemented, flexible demand resources (y in mathcalDF) are characterized by: a) maximum deferrable demand as a fraction of available capacity in a particular time step t, rho^max_yzt, b) the maximum time this demand can be advanced and delayed, defined by parameters, tau^advance_yz and tau^delay_yz, respectively and c) the energy losses associated with shifting demand, eta_yz^dflex.\n\nTracking total deferred demand The operational constraints governing flexible demand resources are as follows. The first two constraints model keep track of inventory of deferred demand in each time step. Specifically, the amount of deferred demand remaining to be served (Gamma_yzt) depends on the amount in the previous time step minus the served demand during time step t (Theta_yzt) while accounting for energy losses associated with demand flexibility, plus the demand that has been deferred during the current time step (Pi_yzt). Note that variable Gamma_yzt in mathbbR, forall y in mathcalDF t in mathcalT. Similar to hydro inventory or storage state of charge constraints, for the first time step of the year (or each representative period), we define the deferred demand level based on level of deferred demand in the last time step of the year (or each representative period).\n\nbeginaligned\nGamma_yzt = Gamma_yzt-1 -eta_yz^dflexTheta_yzt +Pi_yzt hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT^interior \nGamma_yzt = Gamma_yzt +tau^period-1 -eta_yz^dflexTheta_yzt +Pi_yzt hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT^start\nendaligned\n\nBounds on available demand flexibility At any given time step, the amount of demand that can be shifted or deferred cannot exceed the maximum deferrable demand, defined by product of the availability factor (rho^max_yt) times the available capacity(Delta^total_yz).\n\nbeginaligned\nPi_yt leq rho^max_yztDelta_yz hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT\nendaligned\n\nMaximum time delay and advancements Delayed demand must then be served within a fixed number of time steps. This is done by enforcing the sum of demand satisfied (Theta_yzt) in the following tau^delay_yz time steps (e.g., t + 1 to t + tau^delay_yz) to be greater than or equal to the level of energy deferred during time step t.\n\nbeginaligned\nsum_e=t+1^t+tau^delay_yzTheta_yze geq Gamma_yzt\n hspace4 cm forall y in mathcalDFz in mathcalZ t in mathcalT\nendaligned\n\nA similar constraints maximum time steps of demand advancement. This is done by enforcing the sum of demand deferred (Pi_yt) in the following tau^advance_y time steps (e.g., t + 1 to t + tau^advance_y) to be greater than or equal to the total level of energy deferred during time t (-Gamma_yt). The negative sign is included to account for the established sign convention that treat demand deferred in advance of the actual demand is defined to be negative.\n\nbeginaligned\nsum_e=t+1^t+tau^advance_yzPi_yze geq -Gamma_yzt\n hspace4 cm forall y in mathcalDF z in mathcalZ t in mathcalT\nendaligned\n\nIf t is first time step of the year (or the first time step of the representative period), then the above two constraints are implemented to look back over the last n time steps, starting with the last time step of the year (or the last time step of the representative period). This time-wrapping implementation is similar to the time-wrapping implementations used for defining the storage balance constraints for hydropower reservoir resources and energy storage resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Concept_Overview/objective_function/#Objective-Function","page":"Objective Function","title":"Objective Function","text":"","category":"section"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The objective function of GenX minimizes total annual electricity system costs over the following components shown in the below equation:","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"beginaligned\n textmin quad\n sum_y in mathcalG sum_z in mathcalZ left((pi^INVEST_yz times overlineOmega^size_yz times Omega_yz) + (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right) + \n sum_y in mathcalO sum_z in mathcalZ left( (pi^INVESTenergy_yz times Omega^energy_yz) + (pi^FOMenergy_yz times Delta^totalenergy_yz)right) + \n sum_y in mathcalO^asym sum_z in mathcalZ left( (pi^INVESTcharge_yz times Omega^charge_yz) + (pi^FOMcharge_yz times Delta^totalcharge_yz)right) + \n sum_y in mathcalG sum_z in mathcalZ sum_t in mathcalT left( omega_ttimes(pi^VOM_yz + pi^FUEL_yz)times Theta_yztright) + sum_y in mathcalO cup DF sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMcharge_yz times Pi_yztright) + \n sum_s in mathcalS sum_z in mathcalZ sum_t in mathcalT left(omega_t times n_s^slope times Lambda_sztright) + sum_t in mathcalT left(omega_t times pi^unmet_rsv times r^unmet_tright) \n sum_y in mathcalH sum_z in mathcalZ sum_t in mathcalTleft(omega_t times pi^START_yz times chi_sztright) + \n sum_l in mathcalLleft(pi^TCAP_l times bigtriangleupvarphi^max_lright) + \n sum_y in mathcalVS^inv sum_z in mathcalZ left( (pi^INVEST inv_yz times Omega^inv_yz)\n + (pi^FOM inv_yz times Delta^totalinv_yz)right) + \n sum_y in mathcalVS^pv sum_z in mathcalZ left( (pi^INVEST pv_yz times Omega^pv_yz)\n + (pi^FOM pv_yz times Delta^totalpv_yz)right) + \n sum_y in mathcalVS^wind sum_z in mathcalZ left( (pi^INVEST wind_yz times Omega^pv_yz)\n + (pi^FOM wind_yz times Delta^totalwind_yz)right) + \n sum_y in mathcalVS^asymdcdis sum_z in mathcalZ left( (pi^INVESTdcdis_yz times Omega^dcdis_yz)\n + (pi^FOMdcdis_yz times Delta^totaldcdis_yz)right) + \n sum_y in mathcalVS^asymdccha sum_z in mathcalZ left( (pi^INVESTdccha_yz times Omega^dccha_yz)\n + (pi^FOMdccha_yz times Delta^totaldccha_yz)right) + \n sum_y in mathcalVS^asymacdis sum_z in mathcalZ left( (pi^INVESTacdis_yz times Omega^acdis_yz)\n + (pi^FOMacdis_yz times Delta^totalacdis_yz)right) + \n sum_y in mathcalVS^asymaccha sum_z in mathcalZ left( (pi^INVESTaccha_yz times Omega^accha_yz)\n + (pi^FOMaccha_yz times Delta^totalaccha_yz)right) + \n sum_y in mathcalVS^pv sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMpv_yztimes eta^inverter_yz times Theta^pv_yztright) + \n sum_y in mathcalVS^wind sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMwind_yz times Theta^wind_yztright) + \n sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMdcdis_yz timeseta^inverter_yz times Theta^dc_yztright) + \n sum_y in mathcalVS^symdc cup mathcalVS^asymdccha sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMdccha_yz times fracPi^dc_yzteta^inverter_yzright) + \n sum_y in mathcalVS^symac cup mathcalVS^asymacdis sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMacdis_yz times Theta^ac_yztright) + \n sum_y in mathcalVS^symac cup mathcalVS^asymaccha sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMaccha_yz times Pi^ac_yztright) \nendaligned","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The first summation represents the fixed costs of generation/discharge over all zones and technologies, which reflects the sum of the annualized capital cost, pi^INVEST_yz, times the total new capacity added (if any), plus the Fixed O&M cost, pi^FOM_yz, times the net installed generation capacity, overlineOmega^size_yz times Delta^total_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources (y in mathcalO cup mathcalVS^stor). This term includes the sum of the annualized energy capital cost, pi^INVESTenergy_yz, times the total new energy capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed energy storage capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components (y in mathcalO^asym). This term includes the sum of the annualized charging power capital cost, pi^INVESTcharge_yz, times the total new charging power capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed charging power capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The fourth and fifth summations correspond to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, pi^FUEL_yz (if any), plus variable O&M cost, pi^VOM_yz times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, yinmathcalDF) in time step t, Theta_yzt, and the weight of each time step t, omega_t. The fifth summation represents the variable charging O&M cost, pi^VOMcharge_yz times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step t , Pi_yzt and the annual weight of time step t,omega_t. The weight of each time step, omega_t, is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, t such that the sum of omega_t forall t in T = 8760, approximating annual operating costs.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The sixth summation represents the total cost of unserved demand across all segments s of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), n_s^slope, times the amount of non-served energy, Lambda_yzt, for each segment on each zone during each time step (weighted by omega_t).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The seventh summation represents the total cost of not meeting hourly operating reserve requirements (if modeled), where pi^unmet_rsv is the cost penalty per unit of non-served reserve requirement, and r^unmet_t is the amount of non-served reserve requirement in each time step (weighted by omega_t).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. y in mathcalUC), equal to the cost of start-up, pi^START_yz, times the number of startup events, chi_yzt, for the cluster of units in each zone and time step (weighted by omega_t).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The ninth term corresponds to the transmission reinforcement or construction costs, for each transmission line (if modeled). Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, pi^TCAP_l, times the additional transmission capacity variable, bigtriangleupvarphi^max_l. Note that fixed O&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The tenth term onwards specifically relates to the breakdown investment, fixed O&M, and variable O&M costs associated with each configurable component of a co-located VRE and storage resource. The tenth term represents to the fixed cost of installed inverter capacity and is summed over only the co-located resources with an inverter component (y in mathcalVS^inv). This term includes the sum of the annualized inverter capital cost, pi^INVESTinv_yz, times the total new inverter capacity added (if any), plus the Fixed O&M cost, pi^FOM inv_yz, times the net installed inverter capacity, Delta^totalinv_yz (e.g., existing capacity less retirements plus additions). The eleventh term represents the fixed cost of installed solar PV capacity and is summed over only the co-located resources with a solar PV component (y in mathcalVS^pv). This term includes the sum of the annualized solar PV capital cost, pi^INVESTpv_yz, times the total new solar PV capacity added (if any), plus the Fixed O&M cost, pi^FOM pv_yz, times the net installed solar PV capacity, Delta^totalpv_yz (e.g., existing capacity less retirements plus additions). The twelveth term represents the fixed cost of installed wind capacity and is summed over only the co-located resources with a wind component (y in mathcalVS^wind). This term includes the sum of the annualized wind capital cost, pi^INVESTwind_yz, times the total new wind capacity added (if any), plus the Fixed O&M cost, pi^FOM wind_yz, times the net installed wind capacity, Delta^totalwind_yz (e.g., existing capacity less retirements plus additions). The thirteenth term represents the fixed cost of installed storage DC discharge capacity and is summed over only the co-located resources with an asymmetric storage DC discharge component (y in mathcalVS^asymdcdis). This term includes the sum of the annualized storage DC discharge capital cost, pi^INVESTdcdis_yz, times the total new storage DC discharge capacity added (if any), plus the Fixed O&M cost, pi^FOM dc dis_yz, times the net installed storage DC discharge capacity, Delta^totaldcdis_yz (e.g., existing capacity less retirements plus additions). The fourteenth term represents the fixed cost of installed storage DC charge capacity and is summed over only the co-located resources with an asymmetric storage DC charge component (y in mathcalVS^asymdccha). This term includes the sum of the annualized storage DC charge capital cost, pi^INVESTdccha_yz, times the total new storage DC charge capacity added (if any), plus the Fixed O&M cost, pi^FOM dc cha_yz, times the net installed storage DC charge capacity, Delta^totaldccha_yz (e.g., existing capacity less retirements plus additions). The fifteenth term represents the fixed cost of installed storage AC discharge capacity and is summed over only the co-located resources with an asymmetric storage AC discharge component (y in mathcalVS^asymacdis). This term includes the sum of the annualized storage AC discharge capital cost, pi^INVESTacdis_yz, times the total new storage AC discharge capacity added (if any), plus the Fixed O&M cost, pi^FOM ac dis_yz, times the net installed storage AC discharge capacity, Delta^totalacdis_yz (e.g., existing capacity less retirements plus additions). The sixteenth term represents to the fixed cost of installed storage AC charge capacity and is summed over only the co-located resources with an asymmetric storage AC charge component (y in mathcalVS^asymaccha). This term includes the sum of the annualized storage AC charge capital cost, pi^INVESTaccha_yz, times the total new storage AC charge capacity added (if any), plus the Fixed O&M cost, pi^FOM ac cha_yz, times the net installed storage AC charge capacity, Delta^totalaccha_yz (e.g., existing capacity less retirements plus additions).","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"The seventeeth term onwards corresponds to the operational cost across all zones, technologies, and time steps for co-located VRE and storage resources. The seventeenth summation represents the variable O&M cost, pi^VOMpv_yz, times the energy generation by solar PV resources (yinmathcalVS^pv) in time step t, Theta^pv_yzt, the inverter efficiency, eta^inverter_yz, and the weight of each time step t, omega_t. The eighteenth summation represents the variable O&M cost, pi^VOMwind_yz, times the energy generation by wind resources (yinmathcalVS^wind) in time step t, Theta^wind_yzt, and the weight of each time step t, omega_t. The nineteenth summation represents the variable O&M cost, pi^VOMdcdis_yz, times the energy discharge by storage DC components (yinmathcalVS^symdc cup mathcalVS^asymdcdis) in time step t, Theta^dc_yzt, the inverter efficiency, eta^inverter_yz, and the weight of each time step t, omega_t. The twentieth summation represents the variable O&M cost, pi^VOMdccha_yz, times the energy withdrawn by storage DC components (yinmathcalVS^symdc cup mathcalVS^asymdccha) in time step t, Pi^dc_yzt, and the weight of each time step t, omega_t, and divided by the inverter efficiency, eta^inverter_yz. The twenty-first summation represents the variable O&M cost, pi^VOMacdis_yz, times the energy discharge by storage AC components (yinmathcalVS^symac cup mathcalVS^asymacdis) in time step t, Theta^ac_yzt, and the weight of each time step t, omega_t. The twenty-second summation represents the variable O&M cost, pi^VOMaccha_yz, times the energy withdrawn by storage AC components (yinmathcalVS^symac cup mathcalVS^asymaccha) in time step t, Pi^ac_yzt, and the weight of each time step t, omega_t. ","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"In summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions:","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"where and how to invest on capacity,\nhow to dispatch or operate that capacity,\nwhich consumer demand segments to serve or curtail,\nhow to cycle and commit thermal units subject to unit commitment decisions,\nand where and how to invest in additional transmission network capacity to increase power transfer capacity between zones.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.","category":"page"},{"location":"Model_Concept_Overview/objective_function/","page":"Objective Function","title":"Objective Function","text":"While the objective function is formulated as a cost minimization problem, it is also equivalent to a social welfare maximization problem, with the bulk of demand treated as inelastic and always served, and the utility of consumption for price-elastic consumers represented as a segment-wise approximation, as per the cost of unserved demand summation above.","category":"page"},{"location":"User_Guide/workflow/#User-Guide","page":"Overall workflow","title":"User Guide","text":"","category":"section"},{"location":"User_Guide/workflow/#Introduction","page":"Overall workflow","title":"Introduction","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"GenX is a constrained linear or mixed integer linear optimization model that determines the portfolio of electricity generation, storage, transmission, and demand-side resource investments and operational decisions to meet electricity demand in one or more future planning years at lowest cost, while subject to a variety of power system operational constraints, resource availability limits, and other imposed environmental, market design, and policy constraints.","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Depending on the planning problem or question to be studied, GenX can be configured with varying levels of model resolution and scope, with regards to: ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Temporal resolution of time series data such as electricity demand and renewable energy availability; \nPower system operational detail and unit commitment constraints; \nGeospatial resolution and transmission network representation. ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The model is also capable of representing a full range of conventional and novel electricity resources, including thermal generators, variable renewable resources (wind and solar), run-of-river, reservoir and pumped-storage hydroelectric generators, energy storage devices, demand-side flexibility, demand response, and several advanced technologies such as long-duration energy storage.","category":"page"},{"location":"User_Guide/workflow/#Workflow","page":"Overall workflow","title":"Workflow","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The flexibility of GenX is achieved through a modular and transparent code structure developed in Julia + JuMP. The software workflow includes two main steps: ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Model configuration and building: this step involves the specification of the planning problem to be studied, including time dependent data like electricity demand, renewable energy availability and fuel prices, number and type of resources included in the model, graph representation of the transmission network, and the set of constraints and objectives to be imposed.\nModel execution: once the model is configured, a solver is called to find the optimal solution to the planning problem. The solution is then post-processed to generate a set of output files that can be used for further analysis.","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The next sections in this guide provide more details on how to perform all the steps in the workflow: ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Model settings parameters: genx_settings.yml\nSolver Configuration: [solver_name]_settings.yml\nGenX Inputs\nTime-domain reduction: time_domain_reduction.yml (optional)\nMulti-stage setup: multi_stage_settings.yml (optional)\nRunning the model\nGenX Outputs","category":"page"},{"location":"User_Guide/workflow/#Details-of-running-a-GenX-case","page":"Overall workflow","title":"Details of running a GenX case","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"This section details as to what happens in the process of running a GenX case. As a first step, the GenX package and the desired solver (is it's anyting other than the default solver, HiGHS; for instance, Gurobi) are loaded ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"using GenX\nusing Gurobi\noptimizer=Gurobi.Optimizer","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The next command the user needs to run is the following:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"run_genx_case!(\"\", optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"Contingent upon whether a single stage model or a multi-stage model is intended to be run, the above function, inturn makes calls to either of these two functions: For single-stage case:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"run_genx_case_simple!(case, mysetup, optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"From within this function, if time-domain reduction (TDR) is needed, GenX first checks \twhether there already is time domain clustered data (in order to avoid duplication of efforts) by running ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"prevent_doubled_timedomainreduction(case)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"and if the function","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"!time_domain_reduced_files_exist(TDRpath)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"returns true value, it then runs","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"cluster_inputs(case, settings_path, mysetup)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"to generate the time-domain clustered data for the time-series. -OR- For multi-stage case:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"run_genx_case_multistage!(case, mysetup, optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"In this case also, the TDR clustering is done in a similar way, exxcept for the fact that if TDRSettingsDict[\"MultiStageConcatenate\"] is set to 0, the TDR clustering is done individually for each stage. Otherwise, the clustering is done for all the stages together. The next step is configuring the solver, which is done by","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"OPTIMIZER = configure_solver(settings_path, optimizer)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The call to configure_solver first gets the particular solver that is being used to solve the particular case at hand, which then calls a function specific to that solver in order to use either the default values of the solver settings parameter or, any other set of values, specified in the settings YAML file for that particular solver. ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The configuration of solver is followed by loading the input files by running the following function:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"myinputs = load_inputs(mysetup, case)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The above function in its turn calls separate functions to load different resources, demand data, fuels data etc. and returns the dictionary myinputs populated by the input data. The next function call is to generate the model ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"time_elapsed = @elapsed EP = generate_model(mysetup, myinputs, OPTIMIZER)\nprintln(\"Time elapsed for model building is\")\nprintln(time_elapsed)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The above function call instantiates the different decision variables, constraints, and objective function expressions from the input data. It can be seen that we also keep track of the time required to build the model. Follwoing this, the solve_model function makes the call to the solver and return the results as well as the solve time. ","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"EP, solve_time = solve_model(EP, mysetup)\nmyinputs[\"solve_time\"] = solve_time # Store the model solve time in myinputs","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"For writing the results, we invoke the following function:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"outputs_path = get_default_output_folder(case)\nelapsed_time = @elapsed outputs_path = write_outputs(EP, outputs_path, mysetup, myinputs)","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The call to the writeoutputs() function in turn calls a series of functions (writecapacity, write_power etc.) each of which querries the respective decision variables and creates dataframes, eventually outputting the results to separate CSV files. ","category":"page"},{"location":"User_Guide/workflow/#Single-and-Multi-stage-investment-planning","page":"Overall workflow","title":"Single and Multi-stage investment planning","text":"","category":"section"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"In addition to the standard single-stage planning mode, in which the produces a single snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions, recent improvements in the GenX source code (part of v0.3 release) enable its use for studying long-term evolution of the power system across multiple investment stages. GenX can be used to study multi-stage power system planning in the following two ways:","category":"page"},{"location":"User_Guide/workflow/","page":"Overall workflow","title":"Overall workflow","text":"The user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here.\nThe user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as \"myopic\" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.","category":"page"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/#Curtailable-Variable-Renewables","page":"Curtailable Variable Renewable","title":"Curtailable Variable Renewables","text":"","category":"section"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/","page":"Curtailable Variable Renewable","title":"Curtailable Variable Renewable","text":"Modules = [GenX]\nPages = [\"curtailable_variable_renewable.jl\"]","category":"page"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/#GenX.curtailable_variable_renewable!-Tuple{JuMP.Model, Dict, Dict}","page":"Curtailable Variable Renewable","title":"GenX.curtailable_variable_renewable!","text":"curtailable_variable_renewable!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the constraints for operation of variable renewable energy (VRE) resources whose output can be curtailed (y in mathcalVRE), such as utility-scale solar PV or wind power resources or run-of-river hydro resources that can spill water. The operational constraints for VRE resources are a function of each technology's time-dependent hourly capacity factor (or availability factor, rho^max_yzt), in per unit terms, and the total available capacity (Delta^total_yz).\n\nPower output in each time step For each VRE technology type y and model zone z, the model allows for incorporating multiple bins with different parameters for resource quality (rho^max_yzt), maximum availability (overlineOmega_yz) and investment cost (Pi^INVEST_yz, for example, due to interconnection cost differences). We define variables related to installed capacity (Delta_yz) and retired capacity (Delta_yz) for all resource bins for a particular VRE resource type y and zone z (overlinemathcalVRE^yz). However, the variable corresponding to power output in each timestep is only defined for the first bin. Parameter VREIndex_yz, is used to keep track of the first bin, where VREIndex_yz=1 for the first bin and VREIndex_yz=0 for the remaining bins. This approach allows for modeling many different bins per VRE technology type and zone while significantly reducing the number of operational variable (related to power output for each time step from each bin) added to the model with every additional bin. Thus, the maximum power output for each VRE resource type in each zone is given by the following equation:\n\nbeginaligned\n\tTheta_yzt leq sum_(xz)in overlinemathcalVRE^xzrho^max_xzt times Delta^total_xz hspace2 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\nThe above constraint is defined as an inequality instead of an equality to allow for VRE power output to be curtailed if desired. This adds the possibility of introducing VRE curtailment as an extra degree of freedom to guarantee that generation exactly meets demand in each time step. Note that if OperationalReserves=1 indicating that frequency regulation and operating reserves are modeled, then this function calls curtailable_variable_renewable_operational_reserves!(), which replaces the above constraints with a formulation inclusive of reserve provision.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/curtailable_variable_renewable/#GenX.curtailable_variable_renewable_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Curtailable Variable Renewable","title":"GenX.curtailable_variable_renewable_operational_reserves!","text":"curtailable_variable_renewable_operational_reserves!(EP::Model, inputs::Dict)\n\nWhen modeling operating reserves, this function is called by curtailable_variable_renewable(), which modifies the constraint for maximum power output in each time step from VRE resources to account for procuring some of the available capacity for frequency regulation (f_yzt) and upward operating (spinning) reserves (r_yzt).\n\nbeginaligned\n\tTheta_yzt + f_yzt + r_yzt leq sum_(xz)in overlinemathcalVRE^xzrho^max_xzttimes Delta^total_xz hspace01 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\nThe amount of downward frequency regulation reserves also cannot exceed the current power output.\n\nbeginaligned\n\tf_yzt leq Theta_yzt\n\tforall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\nThe amount of frequency regulation and operating reserves procured in each time step is bounded by the user-specified fraction (upsilon^reg_yz,upsilon^rsv_yz) of available capacity in each period for each reserve type, reflecting the maximum ramp rate for the VRE resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nbeginaligned\n\tr_yzt leq upsilon^rsv_yz sum_(xz)in overlinemathcalVRE^xzrho^max_xzttimes Delta^total_xz hspace1 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT \n\tf_yzt leq upsilon^reg_yz sum_(xz)in overlinemathcalVRE^xzrho^max_xzttimes Delta^total_xz hspace1 cm forall yz in (yz)VREIndex_yz=1 z in mathcalZt in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"third_party_genx/#pygenx:-Python-interface-for-GenX","page":"Third Party Extensions","title":"pygenx: Python interface for GenX","text":"","category":"section"},{"location":"third_party_genx/","page":"Third Party Extensions","title":"Third Party Extensions","text":"Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation. ","category":"page"},{"location":"third_party_genx/#Simple-GenX-Case-Runner:-For-automated-sequential-batch-run-for-GenX","page":"Third Party Extensions","title":"Simple GenX Case Runner: For automated sequential batch run for GenX","text":"","category":"section"},{"location":"third_party_genx/","page":"Third Party Extensions","title":"Third Party Extensions","text":"It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner","category":"page"},{"location":"third_party_genx/#Bug-and-feature-requests-and-contact-info","page":"Third Party Extensions","title":"Bug and feature requests and contact info","text":"","category":"section"},{"location":"third_party_genx/","page":"Third Party Extensions","title":"Third Party Extensions","text":"If you would like to report a bug in the code or request a feature, please use our Issue Tracker. If you're unsure or have questions on how to use GenX that are not addressed by the above documentation, please reach out to Sambuddha Chakrabarti (sc87@princeton.edu), Luca Bonaldo (lucabonaldo@princeton.edu), Jesse Jenkins (jdj2@princeton.edu) or Dharik Mallapragada (dharik@mit.edu).","category":"page"},{"location":"User_Guide/running_TDR/#Running-a-case-with-Time-Domain-Reduction","page":"Running the Time-domain Reduction","title":"Running a case with Time Domain Reduction","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"There are two ways to run a case with a reduced (e.g. less than full-year) temporal resolution.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Let GenX perform the time domain reduction before optimizing.\nBring your own clustered data","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"It's also possible for GenX perform clustering separately from the optimization task. ","category":"page"},{"location":"User_Guide/running_TDR/#Method-1:-Let-GenX-perform-the-time-domain-reduction-(clustering)","page":"Running the Time-domain Reduction","title":"Method 1: Let GenX perform the time domain reduction (clustering)","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Set TimeDomainReduction: 1in the GenX settings for the case.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"When the case is run (but before the optimization model is built), reduced time series data will be output to a folder within the case, (typically) TDR_results. Note that if the data already exists in that folder, it will not be overwritten. If a user wants to change the time domain reduction settings and try again, the folder should be deleted before the case is run.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The clustering is done according to the settings in time_domain_reduction.yml. These are described in the Inputs section of data_documentation.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Time domain clustering can only be performed on data which represents a single contiguous period: typically a year of 8760 or 8736 hours.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The header of the file Load_data.csv in the main case folder will typically look like this:","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"..., Rep_Periods, Timesteps_per_Rep_Period, Sub_Weights, ...\n 1, 8760, 8760,","category":"page"},{"location":"User_Guide/running_TDR/#Method-2:-Bring-your-own-clustered-data","page":"Running the Time-domain Reduction","title":"Method 2: Bring your own clustered data","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The second method is to use an external program to generate the reduced ('clustered') time series data. For instance, PowerGenome has a capability to construct GenX cases with clustered time series data.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Running using this method requires setting TimeDomainReduction: 0 in the GenX settings for the case.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Clustered time series data requires specifying the clustering data using three columns in Load_data.csv: Rep_Periods, Timesteps_per_Rep_Period, and Sub_Weights. For example, a problem representing a full year via 3 representative weeks, and where the first week represents one which is twice as common as the others, would look like","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"..., Rep_Periods, Timesteps_per_Rep_Period, Sub_Weights, ...\n 3, 168, 4368.0,\n 2184.0,\n 2184.0,","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"In this example, the first week represents a total of 26*168 = 4368 hours over a full year.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"The time series data are written in single unbroken columns: in this example, the Time_Index ranges from 1 to 504.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"For problems involving Long Duration Storage, a file Period_map.csv is necessary to describe how these representative periods occur throughout the modeled year.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"See also the Time-domain reduction.","category":"page"},{"location":"User_Guide/running_TDR/#Performing-time-domain-reduction-(TDR)-separately-from-optimization","page":"Running the Time-domain Reduction","title":"Performing time domain reduction (TDR) separately from optimization","text":"","category":"section"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Added in 0.3.4","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"It may be useful to perform time domain reduction (TDR) (or \"clustering\") on a set of inputs before using them as part of full GenX optimization task. For example, a user might want to test various TDR settings and examine the resulting clustered inputs. This can now be performed using the run_timedomainreduction! function.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"$ julia --project=/home/youruser/GenX\n\njulia> using GenX\njulia> run_timedomainreduction!(\"/path/to/case\")","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"This function will obey the settings in path/to/case/settings/time_domain_reduction_settings.yml. It will output the resulting clustered time series files in the case.","category":"page"},{"location":"User_Guide/running_TDR/","page":"Running the Time-domain Reduction","title":"Running the Time-domain Reduction","text":"Running this function will overwrite these files in the case. This is done with the expectation that the user is trying out various settings.","category":"page"},{"location":"Model_Reference/Resources/thermal/#Thermal","page":"Thermal","title":"Thermal","text":"","category":"section"},{"location":"Model_Reference/Resources/thermal/","page":"Thermal","title":"Thermal","text":"Modules = [GenX]\nPages = [\"thermal.jl\", \"effective_capacity.jl\"]","category":"page"},{"location":"Model_Reference/Resources/thermal/#GenX.thermal!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal","title":"GenX.thermal!","text":"thermal!(EP::Model, inputs::Dict, setup::Dict)\n\nThe thermal module creates decision variables, expressions, and constraints related to thermal power plants e.g. coal, oil or natural gas steam plants, natural gas combined cycle and combustion turbine plants, nuclear, hydrogen combustion etc. This module uses the following 'helper' functions in separate files: thermal_commit() for thermal resources subject to unit commitment decisions and constraints (if any) and thermal_no_commit() for thermal resources not subject to unit commitment (if any).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal/#GenX.thermal_plant_effective_capacity-Tuple{Any, Any, Vector{Int64}, Int64, Vector{Int64}}","page":"Thermal","title":"GenX.thermal_plant_effective_capacity","text":"thermal_plant_effective_capacity(EP::Model,\n inputs::Dict,\n resources::Vector{Int},\n capres_zone::Int,\n timesteps::Vector{Int})::Matrix{Float64}\n\nEffective capacity in a capacity reserve margin zone for certain resources in the given timesteps.\n\n\n\n\n\n","category":"method"},{"location":"Tutorials/Tutorial_1_configuring_settings/#Tutorial-1:-Configuring-Settings","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"section"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"GenX is easy to customize to fit a variety of problems. In this tutorial, we show which settings are available to change, what their defaults are, and how to change them in your code.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/#What-settings-are-there?","page":"Tutorial 1: Configuring Settings","title":"What settings are there?","text":"","category":"section"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"There are 21 settings available to edit in GenX, found in the file genx_settings.yml. These settings are described at the Model settings parameters page of the documentation. The file is located in the settings folder in the working directory. To change the location of the file, edit the settings_path variable in Run.jl within your directory.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Most settings are set as either 0 or 1, which correspond to whether or not to include a specifc feature. For example, to use TimeDomainReduction, you would set its parameter to 0 within genx_settings.yml. If you would like to run GenX without it, you would set its parameter to 1.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Other settings, such as CO2Cap, have more options corresponding to integers, while some settings such as ModelingtoGenerateAlternativeSlack take a numerical input directly (in this case, the slack value). Two settings, Solver and TimeDomainReductionFolder take in text as input. To learn more about different solvers, read here. For TimeDomainReductionFolder, specify the name of the directory you wish to see the results in. For a more comprehensive description of the input options, see the documentation linked above.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"To see how changing the settings affects the outputs, see Tutorials 3 and 7.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Below is the settings file for example_systems/1_three_zones:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"All genx_settings.yml files in Example_Systems specify most parameters. When configuring your own settings, however, it is not necessary to input all parameters as defaults are specified for each one in configure_settings.jl.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"To open genx_settings.yml in Jupyter, use the function YAML.load(open(...)) and navigate to file in the desired directory:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"using YAML\ngenx_settings_SNE = YAML.load(open(\"example_systems/1_three_zones/settings/genx_settings.yml\"))","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":" Dict{Any, Any} with 19 entries:\n \"NetworkExpansion\" => 1\n \"ModelingToGenerateAlternativeIterations\" => 3\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 0\n \"PrintModel\" => 0\n \"TimeDomainReduction\" => 1\n \"Trans_Loss_Segments\" => 1\n \"CapacityReserveMargin\" => 0\n \"ModelingtoGenerateAlternativeSlack\" => 0.1\n \"MethodofMorris\" => 0\n \"StorageLosses\" => 1\n \"MultiStage\" => 0\n \"OverwriteResults\" => 0\n \"UCommit\" => 2\n \"ModelingToGenerateAlternatives\" => 0\n \"MaxCapReq\" => 0\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"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 example_systems/1_three_zones to contain no parameters:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"new_params = Dict() # Empty dictionary\nYAML.write_file(\"example_systems/1_three_zones/settings/genx_settings.yml\", new_params)","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"The empty file will look like this:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Now, we run GenX and output the file capacity.csv from the Results folder. To do this, we use the function include, which takes a .jl file and runs it in jupyter notebook:","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"include(\"example_systems/1_three_zones/Run.jl\")","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":" Configuring Settings\n Configuring Solver\n Loading Inputs\n Reading Input CSV Files\n Network.csv Successfully Read!\n Demand (load) data Successfully Read!\n Fuels_data.csv Successfully Read!\n\n\n [ Info: Thermal.csv Successfully Read.\n [ Info: Vre.csv Successfully Read.\n [ Info: Storage.csv Successfully Read.\n [ Info: Resource_minimum_capacity_requirement.csv Successfully Read.\n\n Summary of resources loaded into the model:\n -------------------------------------------------------\n \tResource type \t\tNumber of resources\n =======================================================\n \tThermal \t\t3\n \tVRE \t\t4\n \tStorage \t\t3\n =======================================================\n Total number of resources: 10\n -------------------------------------------------------\n Generators_variability.csv Successfully Read!\n Validating time basis\n CSV Files Successfully Read In From GenX-Tutorials/Tutorials/example_systems/1_three_zones\n Generating the Optimization Model\n Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Fuel Module\n CO2 Module\n Investment Transmission Module\n Transmission Module\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (No Unit Commitment) Resources Module\n Time elapsed for model building is\n 5.677411542\n Solving Model\n Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 402430 rows, 306077 cols, 1216044 nonzeros\n 334406 rows, 273093 cols, 1179498 nonzeros\n Presolve : Reductions: rows 334406(-208720); columns 273093(-217481); elements 1179498(-265378)\n Solving the presolved LP\n IPX model has 334406 rows, 273093 columns and 1179498 nonzeros\n Input\n Number of variables: 273093\n Number of free variables: 0\n Number of constraints: 334406\n Number of equality constraints: 54616\n Number of matrix entries: 1179498\n Matrix range: [4e-07, 1e+01]\n RHS range: [7e+02, 2e+04]\n Objective range: [1e-01, 1e+05]\n Bounds range: [2e+00, 2e+04]\n Preprocessing\n Dualized model: no\n Number of dense columns: 13\n Range of scaling factors: [5.00e-01, 1.00e+00]\n IPX version 1.0\n Interior Point Solve\n Iter P.res D.res P.obj D.obj mu Time\n 0 7.92e+03 4.68e+04 3.32147673e+12 -5.29874805e+12 3.77e+08 0s\n 1 2.52e+03 9.09e+03 -3.25877734e+12 -7.21381041e+12 1.13e+08 0s\n 2 4.85e+02 2.35e+03 -3.11396725e+11 -5.19621090e+12 2.79e+07 1s\n 3 3.29e+02 3.98e+02 -1.38395149e+11 -1.60011105e+12 1.06e+07 4s\n Constructing starting basis...\n 4 2.79e+02 2.18e+02 -9.20089553e+10 -1.12770108e+12 6.86e+06 21s\n 5 9.53e+00 7.39e+01 9.91668627e+10 -5.58589863e+11 1.62e+06 24s\n 6 3.40e+00 1.42e+01 5.89999652e+10 -1.16297421e+11 3.82e+05 34s\n 7 9.22e-01 2.82e+00 3.17189476e+10 -3.28274389e+10 1.18e+05 39s\n 8 3.21e-01 9.06e-01 1.54947223e+10 -9.43126058e+09 4.16e+04 44s\n 9 1.43e-01 7.07e-02 1.25444514e+10 -2.07076014e+09 2.26e+04 50s\n 10 7.24e-02 2.69e-02 9.56770103e+09 6.98368943e+08 1.36e+04 59s\n 11 5.85e-02 2.34e-02 9.04050442e+09 9.72471748e+08 1.23e+04 76s\n 12 4.07e-02 1.86e-02 8.41352551e+09 1.36107427e+09 1.07e+04 91s\n 13 2.13e-02 1.04e-02 7.27813663e+09 2.37139743e+09 7.40e+03 106s\n 14 1.23e-02 9.58e-03 6.85995182e+09 2.42302634e+09 6.65e+03 121s\n 15 6.29e-03 8.69e-03 6.30996161e+09 2.53750169e+09 5.63e+03 137s\n 16 5.05e-03 4.32e-03 6.20375634e+09 3.06005287e+09 4.69e+03 153s\n 17 3.10e-03 2.90e-03 5.81685189e+09 3.42321619e+09 3.56e+03 171s\n 18 2.46e-03 1.90e-03 5.69010358e+09 3.69724506e+09 2.97e+03 193s\n 19 2.17e-03 1.40e-03 5.64332584e+09 3.92063823e+09 2.56e+03 211s\n 20 1.68e-03 1.08e-03 5.58574539e+09 4.00019716e+09 2.36e+03 225s\n 21 1.67e-03 1.03e-03 5.58471864e+09 3.99434084e+09 2.36e+03 239s\n 22 1.62e-03 7.41e-04 5.57432205e+09 4.11610384e+09 2.17e+03 253s\n 23 1.30e-03 5.69e-04 5.49997107e+09 4.19795422e+09 1.94e+03 271s\n 24 1.30e-03 5.50e-04 5.49974396e+09 4.19969138e+09 1.93e+03 290s\n 25 1.02e-03 2.93e-04 5.41913926e+09 4.35952658e+09 1.57e+03 303s\n 26 7.07e-04 2.24e-04 5.30762980e+09 4.42283116e+09 1.31e+03 348s\n 27 6.98e-04 2.04e-04 5.30566881e+09 4.42740669e+09 1.30e+03 368s\n 28 5.75e-04 1.34e-04 5.25404059e+09 4.51834486e+09 1.09e+03 384s\n 29 5.11e-04 5.18e-05 5.23316215e+09 4.57449214e+09 9.78e+02 422s\n 30 3.06e-04 3.13e-05 5.11136554e+09 4.65641695e+09 6.75e+02 463s\n 31 2.48e-04 2.50e-05 5.07790558e+09 4.68190888e+09 5.88e+02 556s\n 32 2.26e-04 1.93e-05 5.07281283e+09 4.69130536e+09 5.66e+02 578s\n 33 1.57e-04 9.24e-06 5.02737766e+09 4.76799355e+09 3.85e+02 610s\n 34 9.42e-05 6.90e-06 4.99047612e+09 4.78396507e+09 3.06e+02 633s\n 35 9.03e-05 5.12e-06 4.98763526e+09 4.80106034e+09 2.77e+02 662s\n 36 3.98e-05 2.82e-06 4.94599392e+09 4.83065342e+09 1.71e+02 671s\n 37 2.58e-05 2.14e-06 4.93651437e+09 4.83728484e+09 1.47e+02 682s\n 38 2.50e-05 1.47e-06 4.93618595e+09 4.83982232e+09 1.43e+02 693s\n 39 2.07e-05 1.07e-06 4.93270993e+09 4.84546499e+09 1.29e+02 703s\n 40 1.99e-05 9.16e-07 4.93246702e+09 4.84544485e+09 1.29e+02 712s\n 41 1.27e-05 5.14e-07 4.92622155e+09 4.85308727e+09 1.08e+02 749s\n 42 6.18e-06 2.78e-07 4.91448823e+09 4.86733398e+09 6.98e+01 756s\n 43 5.75e-06 2.48e-07 4.91402422e+09 4.86791504e+09 6.83e+01 768s\n 44 3.92e-06 2.41e-07 4.91163152e+09 4.86829302e+09 6.42e+01 772s\n 45 3.73e-06 2.31e-07 4.91112985e+09 4.86905244e+09 6.23e+01 776s\n 46 1.94e-06 1.39e-07 4.90762167e+09 4.87412061e+09 4.96e+01 779s\n 47 1.92e-06 1.37e-07 4.90757967e+09 4.87423812e+09 4.94e+01 783s\n 48 1.25e-06 1.12e-07 4.90638638e+09 4.87546419e+09 4.58e+01 787s\n 49 7.47e-07 8.85e-08 4.90346514e+09 4.87810372e+09 3.75e+01 790s\n 50 6.48e-07 7.92e-08 4.90314008e+09 4.87888853e+09 3.59e+01 794s\n 51 4.98e-07 6.91e-08 4.90218004e+09 4.88024918e+09 3.25e+01 797s\n 52 4.95e-07 6.83e-08 4.90215919e+09 4.88024410e+09 3.24e+01 801s\n 53 4.90e-07 6.80e-08 4.90216775e+09 4.88028007e+09 3.24e+01 804s\n 54 4.36e-07 6.78e-08 4.90188796e+09 4.88043523e+09 3.18e+01 806s\n 55 2.99e-07 6.38e-08 4.90162529e+09 4.88076205e+09 3.09e+01 809s\n 56 1.58e-07 4.39e-08 4.90042224e+09 4.88323839e+09 2.54e+01 811s\n 57 1.34e-07 4.22e-08 4.90059270e+09 4.88334431e+09 2.55e+01 813s\n 58 1.04e-07 3.50e-08 4.90003483e+09 4.88459728e+09 2.29e+01 815s\n 59 9.50e-08 3.37e-08 4.90009649e+09 4.88472024e+09 2.28e+01 818s\n 60 8.60e-08 3.33e-08 4.90001976e+09 4.88479577e+09 2.25e+01 820s\n 61 7.03e-08 2.51e-08 4.89985257e+09 4.88580810e+09 2.08e+01 823s\n 62 5.25e-08 2.49e-08 4.89952348e+09 4.88588451e+09 2.02e+01 825s\n 63 4.41e-08 2.20e-08 4.89936497e+09 4.88640830e+09 1.92e+01 827s\n 64 1.95e-08 2.05e-08 4.89921316e+09 4.88671585e+09 1.85e+01 829s\n 65 1.85e-08 2.04e-08 4.89917163e+09 4.88677402e+09 1.84e+01 831s\n 66 9.08e-09 1.50e-08 4.89794260e+09 4.88826475e+09 1.43e+01 832s\n 67 3.26e-09 1.41e-08 4.89826703e+09 4.88831416e+09 1.47e+01 834s\n 68 2.55e-09 9.27e-09 4.89776323e+09 4.89045614e+09 1.08e+01 836s\n 69 4.15e-10 6.43e-09 4.89731419e+09 4.89088355e+09 9.52e+00 838s\n 70 9.46e-11 6.14e-09 4.89657446e+09 4.89107504e+09 8.14e+00 840s\n 71 7.28e-12 2.97e-09 4.89649409e+09 4.89256997e+09 5.81e+00 842s\n 72 8.60e-12 2.23e-09 4.89597151e+09 4.89267917e+09 4.87e+00 844s\n 73 7.28e-12 1.47e-09 4.89583195e+09 4.89300343e+09 4.19e+00 845s\n 74 7.42e-12 1.28e-09 4.89583188e+09 4.89303732e+09 4.14e+00 847s\n 75 7.03e-12 1.11e-09 4.89582547e+09 4.89341063e+09 3.57e+00 849s\n 76 7.28e-12 6.11e-10 4.89574070e+09 4.89395382e+09 2.65e+00 850s\n 77 5.46e-12 1.48e-09 4.89568118e+09 4.89402122e+09 2.46e+00 852s\n 78 7.28e-12 5.82e-10 4.89555416e+09 4.89441725e+09 1.68e+00 854s\n 79 5.46e-12 9.31e-10 4.89551185e+09 4.89441779e+09 1.62e+00 856s\n 80 7.28e-12 8.00e-10 4.89548266e+09 4.89444930e+09 1.53e+00 858s\n 81 5.46e-12 4.66e-10 4.89540821e+09 4.89457401e+09 1.23e+00 859s\n 82 3.64e-12 4.95e-10 4.89518737e+09 4.89480554e+09 5.65e-01 861s\n 83 7.28e-12 1.03e-09 4.89518640e+09 4.89481077e+09 5.56e-01 864s\n 84 5.46e-12 8.59e-10 4.89516124e+09 4.89485596e+09 4.52e-01 866s\n 85 3.64e-12 5.97e-10 4.89510929e+09 4.89488390e+09 3.34e-01 869s\n 86 3.64e-12 7.28e-10 4.89511555e+09 4.89489396e+09 3.28e-01 870s\n 87 3.64e-12 9.75e-10 4.89509232e+09 4.89493928e+09 2.27e-01 872s\n 88 5.46e-12 1.35e-09 4.89508607e+09 4.89497465e+09 1.65e-01 875s\n 89 5.46e-12 2.34e-09 4.89507160e+09 4.89500290e+09 1.02e-01 877s\n 90 3.64e-12 4.66e-10 4.89506888e+09 4.89501168e+09 8.47e-02 879s\n 91 3.64e-12 8.15e-10 4.89505281e+09 4.89502676e+09 3.86e-02 882s\n 92 7.28e-12 2.90e-09 4.89504804e+09 4.89503126e+09 2.48e-02 884s\n 93 7.28e-12 3.11e-09 4.89504828e+09 4.89503139e+09 2.50e-02 886s\n 94 3.64e-12 3.94e-09 4.89504182e+09 4.89503147e+09 1.53e-02 887s\n 95 7.28e-12 4.55e-09 4.89503900e+09 4.89503404e+09 7.34e-03 889s\n 96 7.28e-12 3.97e-09 4.89503797e+09 4.89503587e+09 3.11e-03 891s\n 97 3.64e-12 7.99e-09 4.89503736e+09 4.89503634e+09 1.50e-03 893s\n 98 3.64e-12 7.41e-09 4.89503673e+09 4.89503642e+09 4.55e-04 895s\n 99 3.64e-12 9.50e-09 4.89503663e+09 4.89503648e+09 2.22e-04 897s\n 100* 3.64e-12 1.32e-08 4.89503652e+09 4.89503651e+09 1.82e-05 899s\n 101* 3.64e-12 1.08e-08 4.89503652e+09 4.89503652e+09 2.25e-06 901s\n 102* 3.64e-12 3.12e-08 4.89503652e+09 4.89503652e+09 1.34e-07 903s\n 103* 3.64e-12 1.51e-08 4.89503652e+09 4.89503652e+09 8.82e-09 905s\n Running crossover as requested\n Primal residual before push phase: 1.27e-04\n Dual residual before push phase: 5.11e-05\n Number of dual pushes required: 103575\n Number of primal pushes required: 6498\n Summary\n Runtime: 905.57s\n Status interior point solve: optimal\n Status crossover: optimal\n objective value: 4.89503652e+09\n interior solution primal residual (abs/rel): 6.64e-11 / 3.97e-15\n interior solution dual residual (abs/rel): 1.48e-08 / 1.05e-13\n interior solution objective gap (abs/rel): 1.62e-03 / 3.31e-13\n basic solution primal infeasibility: 8.04e-10\n basic solution dual infeasibility: 2.05e-12\n Ipx: IPM optimal\n Ipx: Crossover optimal\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n IPM iterations: 103\n Crossover iterations: 12550\n Objective value : 4.8950365168e+09\n LP solved for primal\n Writing Output\n Time elapsed for writing costs is\n 1.118419208\n Time elapsed for writing capacity is\n 0.3498405\n Time elapsed for writing power is\n 0.784041083\n Time elapsed for writing charge is\n 0.317718542\n Time elapsed for writing capacity factor is\n 0.262756083\n Time elapsed for writing storage is\n 0.144432875\n Time elapsed for writing curtailment is\n 0.235764667\n Time elapsed for writing nse is\n 0.673588083\n Time elapsed for writing power balance is\n 0.533529375\n Time elapsed for writing transmission flows is\n 0.111765375\n Time elapsed for writing transmission losses is\n 0.139880458\n Time elapsed for writing emissions is\n 0.244327417\n Time elapsed for writing reliability is\n 0.163886125\n Time elapsed for writing storage duals is\n 0.43827175\n Time elapsed for writing fuel consumption is\n 0.50627925\n Time elapsed for writing co2 is\n 0.173650209\n Time elapsed for writing price is\n 0.07908475\n Time elapsed for writing energy revenue is\n 0.251686916\n Time elapsed for writing charging cost is\n 0.174489958\n Time elapsed for writing subsidy is\n 0.188284041\n Time elapsed for writing time weights is\n 0.050749417\n Time elapsed for writing net revenue is\n 0.797592334\n Wrote outputs to GenX-Tutorials/Tutorials/example_systems/1_three_zones/results\n Time elapsed for writing is\n 8.276978416","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"The function Run.jl will build and then solve the model according to the specified parameters. These results will then be output into a results folder in the same directory. Note that the results folders are not overwritten with each run.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"using CSV\nusing DataFrames\nresults = CSV.read(open(\"example_systems/1_three_zones/Results/capacity.csv\"),DataFrame)","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"
11×15 DataFrame
RowResourceZoneStartCapRetCapNewCapEndCapCapacityConstraintDualStartEnergyCapRetEnergyCapNewEnergyCapEndEnergyCapStartChargeCapRetChargeCapNewChargeCapEndChargeCap
String31String3Float64Float64Float64Float64String3Float64Float64Float64Float64Float64Float64Float64Float64
1MA_natural_gas_combined_cycle10.00.07394.757394.750.00.00.00.00.00.00.00.00.0
2CT_natural_gas_combined_cycle20.00.02305.822305.820.00.00.00.00.00.00.00.00.0
3ME_natural_gas_combined_cycle30.00.0716.666716.6660.00.00.00.00.00.00.00.00.0
4MA_solar_pv10.00.021186.521186.50.00.00.00.00.00.00.00.00.0
5CT_onshore_wind20.00.011905.511905.50.00.00.00.00.00.00.00.00.0
6CT_solar_pv20.00.016578.816578.80.00.00.00.00.00.00.00.00.0
7ME_onshore_wind30.00.012767.312767.30.00.00.00.00.00.00.00.00.0
8MA_battery10.00.03362.33362.30.00.00.019427.719427.70.00.00.00.0
9CT_battery20.00.05318.365318.360.00.00.027274.127274.10.00.00.00.0
10ME_battery30.00.02095.32095.30.00.00.07096.277096.270.00.00.00.0
11Totaln/a0.00.083631.383631.3n/a0.00.053798.153798.10.00.00.00.0
","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"As you can see, this runs without a problem! To try with your own parameters, edit the new_params dictionary with whatever parameters you'd like to try and run the cells again.Note: to output the results, you'll have to either delete the previous results folder, or input the name of the new results folder (e.g. results_1) when calling CSV.read as above.","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"Finally, let's rewite genx_settings.yml to put the original settings in the example back: ","category":"page"},{"location":"Tutorials/Tutorial_1_configuring_settings/","page":"Tutorial 1: Configuring Settings","title":"Tutorial 1: Configuring Settings","text":"YAML.write_file(\"example_systems/1_three_zones/settings/genx_settings.yml\", genx_settings_TZ)","category":"page"},{"location":"Model_Reference/Resources/storage_all/#Storage-All","page":"Storage All","title":"Storage All","text":"","category":"section"},{"location":"Model_Reference/Resources/storage_all/","page":"Storage All","title":"Storage All","text":"Modules = [GenX]\nPages = [\"storage_all.jl\"]","category":"page"},{"location":"Model_Reference/Resources/storage_all/#GenX.storage_all!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage All","title":"GenX.storage_all!","text":"storage_all!(EP::Model, inputs::Dict, setup::Dict)\n\nSets up variables and constraints common to all storage resources. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Tutorials/Tutorial_6_solver_settings/#Tutorial-6:-Solver-Settings","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Solver Settings","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Though solving the model relies only on optimize, there are a number of ways to change the way in which the model is optimized. This tutorial goes over solver parameters and how they affect the model solution.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#Table-of-Contents","page":"Tutorial 6: Post Processing","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The HiGHs Solver\nFeasibility Tolerance\nPreSolve\nCrossover","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"using YAML\nusing GenX\nusing JuMP\nusing HiGHS\nusing DataFrames\nusing Plots\nusing Plotly","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"case = joinpath(\"example_systems/1_three_zones\") \n\ngenx_settings = GenX.get_settings_path(case, \"genx_settings.yml\");\nwriteoutput_settings = GenX.get_settings_path(case, \"output_settings.yml\")\nsetup = GenX.configure_settings(genx_settings,writeoutput_settings) \nsettings_path = GenX.get_settings_path(case)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Configuring Settings\n\n \"example_systems/1_three_zones/settings\"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"### Create TDR_Results\nif \"TDR_results\" in cd(readdir,case)\n rm(joinpath(case,\"TDR_results\"), recursive=true) \nend\n\nTDRpath = joinpath(case, setup[\"TimeDomainReductionFolder\"])\nsystem_path = joinpath(case, setup[\"SystemFolder\"])\n\nif setup[\"TimeDomainReduction\"] == 1\n GenX.prevent_doubled_timedomainreduction(system_path)\n if !GenX.time_domain_reduced_files_exist(TDRpath)\n println(\"Clustering Time Series Data (Grouped)...\")\n GenX.cluster_inputs(case, settings_path, setup)\n else\n println(\"Time Series Data Already Clustered.\")\n end\nend\n\ninputs = GenX.load_inputs(setup, case)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#The-HiGHS-Solver","page":"Tutorial 6: Post Processing","title":"The HiGHS Solver","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"In the example files, the solver HiGHS. HiGHS is freely available for all to use. Other solvers, such as Gurobi, are available for free for academics. For the purpose of this tutorial, we will be focusing on HiGHS. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"To set the solver preferences, go into the settings folder of your case and select the YAML file of the solver you're using.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"settings_folder = cd(readdir,joinpath(case,\"Settings\")) # Print Settings folder","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" 7-element Vector{String}:\n \".DS_Store\"\n \"clp_settings.yml\"\n \"cplex_settings.yml\"\n \"genx_settings.yml\"\n \"gurobi_settings.yml\"\n \"highs_settings.yml\"\n \"time_domain_reduction_settings.yml\"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings = YAML.load(open(joinpath(case,\"Settings/highs_settings.yml\")))","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Dict{Any, Any} with 6 entries:\n \"Method\" => \"choose\"\n \"Feasib_Tol\" => 0.1\n \"run_crossover\" => \"on\"\n \"TimeLimit\" => 1.0e23\n \"Optimal_Tol\" => 0.1\n \"Pre_Solve\" => \"choose\"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The function configure_highs in src/configure_solver contains a list of default settings for the HiGHS solver","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"There are about 80, so we'll only focus on a few for now. In most cases, you can leave the other settings on default. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The default settings are combined with the settings you specify in highs_settings.yml in configure_highs, which is called from configure_solver in run_genx_case_simple right before the model is generated.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#Feasibility-Tolerance","page":"Tutorial 6: Post Processing","title":"Feasibility Tolerance","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"The parameters Feasib_Tol and Optimal_Tol represent the feasibility of the primal and dual functions respectively. Without going into too much detail, a dual function is an analagous formulation of the original (\"primal\") function whose objective value acts as a lower bound to the primal function. The objective value of the primal function is then the upper bound of the dual function. HiGHS will solve the dual and primal at each time step, then terminate when the solutions of the two are within a certain tolerance range. For more information on how this works specifically in HiGHS, see the HiGHS documentaion. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"If we decrease the tolerance parameters, the objective value becomes closer to the \"true\" optimal value.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# Change tolerance, generate and solve model`\ntols = [1e-7,1e-4,1e-2,1e-1]\nOV = zeros(1,4)\n\nfor i in range(1,length(tols))\n println(\" \")\n println(\"----------------------------------------------------\")\n println(\"Iteration \",i)\n println(\"Tolerance = \",tols[i])\n println(\"----------------------------------------------------\")\n highs_settings[\"Feasib_Tol\"] = tols[i]\n highs_settings[\"Optimal_Tol\"] = tols[i]\n YAML.write_file(joinpath(case,\"settings/highs_settings.yml\"), highs_settings)\n OPTIMIZER1 = GenX.configure_solver(settings_path,HiGHS.Optimizer)\n EP = GenX.generate_model(setup,inputs,OPTIMIZER1)\n GenX.solve_model(EP,setup)\n OV[i] = objective_value(EP)\nend","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Using the smallest tolerance as our base, we can see the error as the tolerance increases:","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"DataFrame([tols[2:end] abs.(OV[2:end] .- OV[1])],[\"Tolerance\", \"Error\"])","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"3×2 DataFrame\n Row\tTolerance\tError\n Float64\t Float64\n ───────────────────────────\n 1\t0.0001\t 0.0\n 2\t0.01\t 1.81899e-12\n 3\t0.1\t 3.45608e-11","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"using Plots\nusing Plotly","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# Plot the error as a function of the tolerance\nplotlyjs()\nPlots.scatter(tols[2:end], abs.(OV[2:end] .- OV[1]),legend=:topleft,\n ylabel=\"Error\", xlabel=\"Tolerance\",size=(920,400),label=:\"Error\",title=\"Tolerance of Solver vs Error\")\nygrid!(:on, :dashdot, 0.1)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#PreSolve","page":"Tutorial 6: Post Processing","title":"PreSolve","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"In optimization, presolve is a stage at the beginning of the solver in which the problem is simplified to remove redunant constraints and otherwise simplify the problem before the optimization itself begins. The default for presolve in GenX is \"choose\", allowing the solver to use presolve only if it will reduce computation time. ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Let's try setting presolve to off and on, then compare computation times.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# First, set tolerances back to original\nhighs_settings[\"Feasib_Tol\"] = 1e-5\nhighs_settings[\"Optimal_Tol\"] = 1e-5\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings) ","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"Pre_Solve\"] = \"off\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER2 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP2 = GenX.generate_model(setup,inputs,OPTIMIZER2)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 18492\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 5544 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 7398 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 27730 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 2 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 18490 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cCapacityResMargin, cESRShare, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cZoneMaxCapReq, cZoneMinCapReq, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eCapResMarBalance, eCapResMarBalanceStor, eCapResMarBalanceThermal, eCapResMarBalanceVRE, eELOSS, eELOSSByZone, eESR, eESRDischarge, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eMaxCapRes, eMaxCapResInvest, eMinCapRes, eMinCapResInvest, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution2 = @elapsed GenX.solve_model(EP2,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Solving LP without presolve or with basis\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 -4.3842305368e+02 Ph1: 19318(12391.6); Du: 5(438.423) 0s\n 18662 9.5083526285e+03 Pr: 3142(5018.36); Du: 0(0.000872182) 5s\n 23359 9.8583752055e+03 Pr: 0(0); Du: 0(1.27565e-13) 6s\n Model status : Optimal\n Simplex iterations: 23359\n Objective value : 9.8583752055e+03\n HiGHS run time : 6.77\n LP solved for primal\n\n 6.84933975","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"Pre_Solve\"] = \"on\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER3 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP3 = GenX.generate_model(setup,inputs,OPTIMIZER3)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 18492\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 5544 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 7398 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 27730 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 2 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 18490 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cCapacityResMargin, cESRShare, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cZoneMaxCapReq, cZoneMinCapReq, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eCapResMarBalance, eCapResMarBalanceStor, eCapResMarBalanceThermal, eCapResMarBalanceVRE, eELOSS, eELOSSByZone, eESR, eESRDischarge, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eMaxCapRes, eMaxCapResInvest, eMinCapRes, eMinCapResInvest, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution3 = @elapsed GenX.solve_model(EP3,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 35947 rows, 17464 cols, 136177 nonzeros\n 34470 rows, 15991 cols, 136110 nonzeros\n Presolve : Reductions: rows 34470(-6202); columns 15991(-2501); elements 136110(-29848)\n Solving the presolved LP\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 -2.9011432493e+00 Ph1: 118(557.293); Du: 15(2.90114) 0s\n 16445 9.8583752055e+03 Pr: 0(0); Du: 0(1.25316e-13) 4s\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n Simplex iterations: 16445\n Objective value : 9.8583752055e+03\n HiGHS run time : 4.55\n LP solved for primal\n\n 4.655439792","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"As we can see, the runtime with PreSolve is shorter, and would be even shorter for a larger system. However, it could introduce numerical inaccuracies. If you find the model is struggling to converge, try turn PreSolve off.","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"# Write PreSolve back to choose\nhighs_settings[\"Pre_Solve\"] = \"choose\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/#Crossover","page":"Tutorial 6: Post Processing","title":"Crossover","text":"","category":"section"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"Crossover is a method in which, at each step of the optimization algorithm, the solution is pushed to the boundary of the solution space. This allows for a potentially more accurate solution, but can be computationally intensive. Let's try turning crossover on and off and see what solutions we get:","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"run_crossover\"] = \"off\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER4 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP4 = GenX.generate_model(setup,inputs,OPTIMIZER4)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Transmission Module\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Minimum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 83192\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 24024 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 20334 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 103509 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 4 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 79492 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxFlow_in, cMaxFlow_out, cMaxLineReinforcement, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cTAuxLimit, cTAuxSum, cTLoss, cZoneMinCapReq, eAvail_Trans_Cap, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eELOSS, eELOSSByZone, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eLosses_By_Zone, eMinCapRes, eMinCapResInvest, eNet_Export_Flows, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceLossesByZone, ePowerBalanceNetExportFlows, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCNetworkExp, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, eTransMax, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vFLOW, vNEW_TRANS_CAP, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vTAUX_NEG, vTAUX_POS, vTLOSS, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution4 = @elapsed GenX.solve_model(EP4,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 123675 rows, 81174 cols, 478190 nonzeros\n 116575 rows, 74076 cols, 478470 nonzeros\n Presolve : Reductions: rows 116575(-31292); columns 74076(-9116); elements 478470(-75676)\n Solving the presolved LP\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 1.9243583242e+03 Pr: 5545(9397.81); Du: 0(3.92542e-09) 0s\n 13530 2.9999821788e+03 Pr: 30131(9.49605e+06); Du: 0(0.0013131) 5s\n 17547 3.5484267823e+03 Pr: 19414(952045); Du: 0(0.00175439) 10s\n 20723 4.7298157079e+03 Pr: 29321(991206); Du: 0(0.00183106) 15s\n 23580 5.7123748112e+03 Pr: 32150(7.12339e+06); Du: 0(0.00148821) 21s\n 26170 6.1864339355e+03 Pr: 23825(7.35638e+06); Du: 0(0.00149712) 26s\n 29149 6.6441899572e+03 Pr: 27775(3.51868e+06); Du: 0(0.00148729) 31s\n 31348 6.8846964690e+03 Pr: 35484(2.8051e+06); Du: 0(0.00139557) 36s\n 33603 6.9920173954e+03 Pr: 24118(2.03558e+06); Du: 0(0.00124593) 42s\n 35671 7.2015870783e+03 Pr: 34108(1.48506e+07); Du: 0(0.00155189) 47s\n 37885 7.4048679609e+03 Pr: 31619(4.35123e+07); Du: 0(0.00179926) 52s\n 40109 7.6356641465e+03 Pr: 25843(2.88592e+06); Du: 0(0.00205301) 58s\n 42353 7.8375259516e+03 Pr: 31443(8.49023e+06); Du: 0(0.00226205) 64s\n 45258 8.1692860958e+03 Pr: 37870(5.26412e+06); Du: 0(0.00255441) 69s\n 48083 8.3152673717e+03 Pr: 40961(1.14875e+07); Du: 0(0.00294817) 75s\n 50545 8.4510258333e+03 Pr: 30790(3.72272e+08); Du: 0(0.00304629) 80s\n 52861 8.5807507297e+03 Pr: 22492(930796); Du: 0(0.00320519) 85s\n 54980 8.6629986832e+03 Pr: 30776(2.08885e+07); Du: 0(0.00337039) 91s\n 57333 8.7549581833e+03 Pr: 26257(1.13046e+06); Du: 0(0.00357615) 96s\n 59389 8.8000584935e+03 Pr: 36678(2.40379e+06); Du: 0(0.00364701) 101s\n 61669 8.8767323679e+03 Pr: 35715(2.44371e+06); Du: 0(0.00390224) 107s\n 63914 8.9782186363e+03 Pr: 43654(3.60725e+06); Du: 0(0.00423026) 113s\n 66084 9.0603325781e+03 Pr: 22220(2.48776e+06); Du: 0(0.00410399) 118s\n 69022 9.1231092369e+03 Pr: 22727(1.78641e+06); Du: 0(0.00444875) 124s\n 71953 9.1538574545e+03 Pr: 22264(5.37124e+06); Du: 0(0.00461629) 129s\n 74846 9.1867207120e+03 Pr: 26970(1.49142e+06); Du: 0(0.00477614) 135s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 77129 9.2058130738e+03 Pr: 1(0.000235421); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n Simplex iterations: 77136\n Objective value : 9.2058130749e+03\n HiGHS run time : 140.51\n LP solved for primal\n\n 140.762363","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"highs_settings[\"run_crossover\"] = \"on\"\nYAML.write_file(joinpath(case,\"Settings/highs_settings.yml\"), highs_settings)\nOPTIMIZER5 = GenX.configure_solver(setup[\"Solver\"], settings_path);\nEP5 = GenX.generate_model(setup,inputs,OPTIMIZER5)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Emissions Module (for CO2 Policy modularization\n Transmission Module\n Dispatchable Resources Module\n Storage Resources Module\n Storage Investment Module\n Storage Core Resources Module\n Storage Resources with Symmetric Charge/Discharge Capacity Module\n Thermal (Unit Commitment) Resources Module\n C02 Policies Module\n Minimum Capacity Requirement Module\n\n A JuMP Model\n Minimization problem with:\n Variables: 83192\n Objective function type: AffExpr\n `AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 24024 constraints\n `AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 20334 constraints\n `AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 103509 constraints\n `VariableRef`-in-`MathOptInterface.EqualTo{Float64}`: 4 constraints\n `VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 79492 constraints\n Model mode: AUTOMATIC\n CachingOptimizer state: EMPTY_OPTIMIZER\n Solver name: HiGHS\n Names registered in the model: cCO2Emissions_systemwide, cMaxCap, cMaxCapEnergy, cMaxCapEnergyDuration, cMaxFlow_in, cMaxFlow_out, cMaxLineReinforcement, cMaxNSE, cMaxRetCommit, cMaxRetEnergy, cMaxRetNoCommit, cMinCap, cMinCapEnergy, cMinCapEnergyDuration, cNSEPerSeg, cPowerBalance, cSoCBalInterior, cSoCBalStart, cTAuxLimit, cTAuxSum, cTLoss, cZoneMinCapReq, eAvail_Trans_Cap, eCFix, eCFixEnergy, eCNSE, eCStart, eCVar_in, eCVar_out, eELOSS, eELOSSByZone, eEmissionsByPlant, eEmissionsByZone, eExistingCap, eExistingCapEnergy, eGenerationByThermAll, eGenerationByVRE, eGenerationByZone, eLosses_By_Zone, eMinCapRes, eMinCapResInvest, eNet_Export_Flows, eObj, ePowerBalance, ePowerBalanceDisp, ePowerBalanceLossesByZone, ePowerBalanceNetExportFlows, ePowerBalanceNse, ePowerBalanceStor, ePowerBalanceThermCommit, eTotalCFix, eTotalCFixEnergy, eTotalCNSE, eTotalCNSET, eTotalCNSETS, eTotalCNetworkExp, eTotalCStart, eTotalCStartT, eTotalCVarIn, eTotalCVarInT, eTotalCVarOut, eTotalCVarOutT, eTotalCap, eTotalCapEnergy, eTransMax, vCAP, vCAPENERGY, vCHARGE, vCO2Cap_slack, vCOMMIT, vFLOW, vNEW_TRANS_CAP, vNSE, vP, vRETCAP, vRETCAPENERGY, vS, vSHUT, vSTART, vTAUX_NEG, vTAUX_POS, vTLOSS, vZERO","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":"solution5 = @elapsed GenX.solve_model(EP5,setup)","category":"page"},{"location":"Tutorials/Tutorial_6_solver_settings/","page":"Tutorial 6: Post Processing","title":"Tutorial 6: Post Processing","text":" Running HiGHS 1.6.0: Copyright (c) 2023 HiGHS under MIT licence terms\n Presolving model\n 123675 rows, 81174 cols, 478190 nonzeros\n 116575 rows, 74076 cols, 478470 nonzeros\n Presolve : Reductions: rows 116575(-31292); columns 74076(-9116); elements 478470(-75676)\n Solving the presolved LP\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 0 1.9243583242e+03 Pr: 5545(9397.81); Du: 0(3.92542e-09) 0s\n 13530 2.9999821788e+03 Pr: 30131(9.49605e+06); Du: 0(0.0013131) 5s\n 17547 3.5484267823e+03 Pr: 19414(952045); Du: 0(0.00175439) 10s\n 20723 4.7298157079e+03 Pr: 29321(991206); Du: 0(0.00183106) 15s\n 23580 5.7123748112e+03 Pr: 32150(7.12339e+06); Du: 0(0.00148821) 21s\n 26170 6.1864339355e+03 Pr: 23825(7.35638e+06); Du: 0(0.00149712) 26s\n 29149 6.6441899572e+03 Pr: 27775(3.51868e+06); Du: 0(0.00148729) 31s\n 31348 6.8846964690e+03 Pr: 35484(2.8051e+06); Du: 0(0.00139557) 36s\n 33603 6.9920173954e+03 Pr: 24118(2.03558e+06); Du: 0(0.00124593) 42s\n 35671 7.2015870783e+03 Pr: 34108(1.48506e+07); Du: 0(0.00155189) 47s\n 37885 7.4048679609e+03 Pr: 31619(4.35123e+07); Du: 0(0.00179926) 52s\n 40109 7.6356641465e+03 Pr: 25843(2.88592e+06); Du: 0(0.00205301) 58s\n 42353 7.8375259516e+03 Pr: 31443(8.49023e+06); Du: 0(0.00226205) 63s\n 45258 8.1692860958e+03 Pr: 37870(5.26412e+06); Du: 0(0.00255441) 69s\n 48083 8.3152673717e+03 Pr: 40961(1.14875e+07); Du: 0(0.00294817) 75s\n 50545 8.4510258333e+03 Pr: 30790(3.72272e+08); Du: 0(0.00304629) 80s\n 52861 8.5807507297e+03 Pr: 22492(930796); Du: 0(0.00320519) 85s\n 54980 8.6629986832e+03 Pr: 30776(2.08885e+07); Du: 0(0.00337039) 91s\n 57333 8.7549581833e+03 Pr: 26257(1.13046e+06); Du: 0(0.00357615) 96s\n 59389 8.8000584935e+03 Pr: 36678(2.40379e+06); Du: 0(0.00364701) 101s\n 61669 8.8767323679e+03 Pr: 35715(2.44371e+06); Du: 0(0.00390224) 107s\n 63914 8.9782186363e+03 Pr: 43654(3.60725e+06); Du: 0(0.00423026) 113s\n 66084 9.0603325781e+03 Pr: 22220(2.48776e+06); Du: 0(0.00410399) 118s\n 69022 9.1231092369e+03 Pr: 22727(1.78641e+06); Du: 0(0.00444875) 124s\n 71953 9.1538574545e+03 Pr: 22264(5.37124e+06); Du: 0(0.00461629) 129s\n 74408 9.1814081583e+03 Pr: 29329(5.2193e+06); Du: 0(0.00473215) 134s\n 77012 9.2060247446e+03 Pr: 0(0); Du: 0(0.00509972) 140s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n 77129 9.2058130738e+03 Pr: 0(0); Du: 0(0.00107487) 140s\n Using EKK dual simplex solver - serial\n Iteration Objective Infeasibilities num(sum)\n 77129 9.2058130738e+03 Pr: 1(0.000235421); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n 77136 9.2058130749e+03 Pr: 0(0); Du: 0(0.000836801) 140s\n Solving the original LP from the solution after postsolve\n Model status : Optimal\n Simplex iterations: 77136\n Objective value : 9.2058130749e+03\n HiGHS run time : 140.44\n LP solved for primal\n\n 140.74829025","category":"page"},{"location":"User_Guide/multi_stage_input/#Multi-stage-setup","page":"Multi-stage Model","title":"Multi-stage setup","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"This section describes the available features, inputs and model components related to formulating and solving multi-stage investment planning problems. Two different types of multi-stage problems can be setup:","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"Perfect foresight: A single multi-stage investment planning problem that simultaneously optimizes capacity and operations across all specified investment stages\nMyopic: Sequential solution of single-stage investment planning for each investment stage, where capacity additions and retirements from the previous stages are used to determine initial (or existing) capacity at the beginning of the current stage. ","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"The table below summarizes the key differences in the two model setups.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" Perfect foresight Myopic\nNo. of optimization problems solved 1 Equal to number of investment stages\nObjective function cost basis Net present value Annualized costs\nPrice/dual variable information available? No Yes","category":"page"},{"location":"User_Guide/multi_stage_input/#Additional-inputs-needed-for-multi-stage-modeling","page":"Multi-stage Model","title":"Additional inputs needed for multi-stage modeling","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/#Input-data-files","page":"Multi-stage Model","title":"Input data files","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"Instead of one set of input files, there is one directory of input files that needs to be provided for each planning period or stage (e.g., “inputs/inputs_p1/” for the first period “inputs/inputs_p2/” for the second period, etc.). Below we list the additional parameters that must be provided in the corresponding stage-specific input files to instantiate a multi-stage planning problem.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" Resourcemultistagedata.csv files\nMin_Retired_Cap_MW Minimum capacity in MW that must retire in this planning stage. Note that for the co-located VRE-STOR module, this value represents the grid connection component.\nMin_Retired_Energy_Cap_MW Minimum energy capacity in MW that must retire in this planning stage. Note that for the co-located VRE-STOR module, this value represents the storage component.\nMin_Retired_Charge_Cap_MW Minimum charge capacity in MW that must retire in this planning stage.\nLifetime The operational lifespan in years of this technology after which it must be retired.\nCapital_Recovery_Period The technology-specific period in years over which initial capital costs must be recovered. Note that for the co-located VRE-STOR module, this value represents the grid connection component.\nWACC The technology-specific weighted average cost of capital. Note that for the co-located VRE-STOR module, this value represents the grid connection component.\nContribute_Min_Retirement {0, 1}, Flag to indicate whether the (retrofitting) resource can contribute to the minimum retirement requirement.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" co-located VRE-STOR resources only\nMin_Retired_Cap_Inverter_MW Minimum inverter capacity in MW AC that must retire in this plannig stage.\nMin_Retired_Cap_Solar_MW Minimum solar PV capacity in MW DC that must retire in this plannig stage.\nMin_Retired_Cap_Wind_MW Minimum wind capacity in MW AC that must retire in this plannig stage.\nMin_Retired_Cap_DischargeDC\\MW Minimum storage DC discharge capacity that must retire in this planning stage with STOR_DC_DISCHARGE = 2.\nMin_Retired_Cap_ChargeDC\\MW Minimum storage DC charge capacity that must retire in this planning stage with STOR_DC_CHARGE = 2.\nMin_Retired_Cap_DischargeAC\\MW Minimum storage AC discharge capacity that must retire in this planning stage with STOR_AC_DISCHARGE = 2.\nMin_Retired_Cap_ChargeAC\\MW Minimum storage AC charge capacity that must retire in this planning stage with STOR_AC_CHARGE = 2.\nCapital_Recovery_Period_DC The technology-specific period in years over which initial capital costs for the inverter component must be recovered.\nCapital_Recovery_Period_Solar The technology-specific period in years over which initial capital costs for the solar PV component must be recovered.\nCapital_Recovery_Period_Wind The technology-specific period in years over which initial capital costs for the wind component must be recovered.\nCapital_Recovery_PeriodDischargeDC The technology-specific period in years over which initial capital costs for the storage DC discharge component must be recovered when STOR_DC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeDC The technology-specific period in years over which initial capital costs for the storage DC charge component must be recovered when STOR_DC_CHARGE = 2.\nCapital_Recovery_PeriodDischargeAC The technology-specific period in years over which initial capital costs for the storage AC discharge component must be recovered when STOR_AC_DISCHARGE = 2.\nCapital_Recovery_PeriodChargeAC The technology-specific period in years over which initial capital costs for the storage AC charge component must be recovered when STOR_DC_CHARGE = 2.\nWACC_DC The line-specific weighted average cost of capital for the inverter component.\nWACC_Solar The line-specific weighted average cost of capital for the solar PV component.\nWACC_Wind The line-specific weighted average cost of capital for the wind component.\nWACC_Discharge_DC The line-specific weighted average cost of capital for the discharging DC storage component with STOR_DC_DISCHARGE = 2.\nWACC_Charge_DC The line-specific weighted average cost of capital for the charging DC storage component with STOR_DC_CHARGE = 2.\nWACC_Discharge_AC The line-specific weighted average cost of capital for the discharging AC storage component with STOR_AC_DISCHARGE = 2.\nWACC_Charge_AC The line-specific weighted average cost of capital for the charging AC storage component with STOR_AC_CHARGE = 2.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" Network.csv\nLine_Max_Flow_Possible_MW The maximum transmission capacity of the line, as opposed to Line_Max_Reinforcement_MW which now specifies the maximum expansion to the line in one stage.\nCapital_Recovery_Period The line-specific period in years over which initial capital costs must be recovered.\nWACC The line-specific weighted average cost of capital.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"note: Allowing retrofitted capacity to not contribute to minimum retirement requirements (`myopic=0` only)\nSpecial considerations must be taken into account when utilizing the retrofit module alongside multi-stage planning, particularly when using a non zero value for the Min_Retired_Cap_MW column in the Resource_multistage_data.csv file.When assigning a non-zero value to the Min_Retired_Cap_MW column in the Resource_multistage_data.csv file, the user can specify whether the model should consider the retrofitted capacity to contribute to the minimum retirement requirement. This is done by setting the Contribute_Min_Retirement column to 1 for the retrofit options in the same retrofit cluster (i.e., same Retrofit_Id).\nBy default, the model assumes that retrofitted capacity contributes to fulfilling minimum retirement requirements.\nShould users wish to exclude retrofitted capacity from contributing to minimum retirement requirements, they must set the Contribute_Min_Retirement column to 0 for all retrofit options within the same retrofit cluster (i.e., sharing the same Retrofit_Id).\nIt's important to note that this additional functionality is not currently supported when myopic=1. In this case, the retrofit options are only allowed to contribute to the minimum retirement requirement.Example 1: Retrofitted capacity is allowed to contribute to the minimum retirement requirement (i.e., retrofit options in the same cluster (Retrofit_Id = 1) all have Contribute_Min_Retirement = 1):Thermal.csv\n\nResource │ Zone | Retrofit | Can_Retrofit | Retrofit_Id | Retrofit_Efficiency\nString │ Int64 | Int64 | Int64 | Int64 | Float64\n─────────────────-┼───────┼─────────────────────────┼────────────-┼────────────────────\ncoal_1 │ 1 │ 0 │ 1 │ 1 │ 0\n20_NH3_retrofit_1 │ 1 │ 1 │ 0 │ 1 │ 0.85\n20_NH3_retrofit_2 │ 1 │ 1 │ 0 │ 1 │ 0.85Resource_multistage_data.csv\n\nResource │ Min_Retired_Cap_MW | Contribute_Min_Retirement\nString │ Float64 | Float64 \n─────────────────-┼────────────────────┼──────────────────────────\ncoal_1 │ 4500 │ 0\n20_NH3_retrofit_1 │ 0 │ 1 <---------\n20_NH3_retrofit_2 │ 0 │ 1 <---------Example 2: Retrofitted capacity is not allowed to contribute to the minimum retirement requirement (i.e., none of the retrofit options in the same cluster (Retrofit_Id = 1) contribute to the minimum retirement requirement (myopic=0)):Thermal.csv: same as Example 1.Resource_multistage_data.csv\n\nResource │ Min_Retired_Cap_MW | Contribute_Min_Retirement\nString │ Float64 | Float64\n─────────────────-┼────────────────────┼──────────────────────────\ncoal_1 │ 4500 │ 0\n20_NH3_retrofit_1 │ 0 │ 0 <---------\n20_NH3_retrofit_2 │ 0 │ 0 <---------And the case where some retrofit options contribute to the minimum retirement requirement and some do not is not currently supported and will be addressed in a future release.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"warning: Warning\nIf 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. ","category":"page"},{"location":"User_Guide/multi_stage_input/#Settings-Files","page":"Multi-stage Model","title":"Settings Files","text":"","category":"section"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":"A separate settings.yml file includes a list of parameters to be specified to formulate the multi-stage planning model.","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" multi_stage_settings.yml\nNumStages The number of model investment planning stages.\nStageLengths A list of lengths of each model stage in years (e.g., [10, 10, 10] for three stages each of length 10). Note that stages could be defined to be of varying length.\nMyopic 0 = perfect foresight, 1 = myopic model (see above table)\nConvergenceTolerance The relative optimality gap used for convergence of the dual dynamic programming algorithm. Only required when Myopic = 0\nWACC Rate used to discount non-technology-specific costs from stage to stage (i.e., the “social discount rate”).","category":"page"},{"location":"User_Guide/multi_stage_input/","page":"Multi-stage Model","title":"Multi-stage Model","text":" time_domain_reduction_settings.yml\nMultiStageConcatenate Designates whether to use time domain reduction for the full set of input data together (1) or to reduce only the first stage data and apply the returned representative periods to the rest of the input data (0).","category":"page"},{"location":"User_Guide/solver_configuration/#Solver-Configuration","page":"Solver Configuration","title":"Solver Configuration","text":"","category":"section"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"To define and solve the optimization problems, GenX relies on JuMP, a domain-specific modeling language for mathematical optimization written in Julia, and on a variety of open-source and commercial solvers. GenX supports the following solvers:","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"Cbc (open-source)\nClp (open-source)\nCPLEX (commercial)\nGurobi (commercial)\nHiGHS (open-source)\nSCIP (open-source)","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"Solver related settings parameters are specified in the appropriate .yml file (e.g. highs_settings.yml, gurobi_settings.yml, etc.), which should be located in the settings folder inside the current working directory (the same settings folder where genx_settings.yml is located). Settings are specific to each solver. Check the Example_Systems folder for examples of solver settings files and parameters. ","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"note: Note\nGenX supplies default settings for most solver settings in the various solver-specific functions found in the src/configure_solver/ directory. To overwrite default settings, you can specify the below Solver specific settings.","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"The following table summarizes the solver settings parameters and their default/possible values. ","category":"page"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"tip: Tip\nSince each solver has its own set of parameters names, together with a description of the parameter, the table provides a reference to the the corresponding solver specific parameter name. ","category":"page"},{"location":"User_Guide/solver_configuration/#Solver-settings-parameters**","page":"Solver Configuration","title":"Solver settings parameters**","text":"","category":"section"},{"location":"User_Guide/solver_configuration/","page":"Solver Configuration","title":"Solver Configuration","text":"Settings Parameter Description\nMethod Algorithm used to solve continuous models or the root node of a MIP model. Generally, barrier method provides the fastest run times for real-world problem set.\n CPLEX: CPX_PARAM_LPMETHOD - Default = 0; See link for more specifications.\n Gurobi: Method - Default = -1; See link for more specifications.\n clp: SolveType - Default = 5; See link for more specifications.\n HiGHS: Method - Default = \"choose\"; See link for more specifications.\nBarConvTol Convergence tolerance for barrier algorithm.\n CPLEX: CPX_PARAM_BAREPCOMP - Default = 1e-8; See link for more specifications.\n Gurobi: BarConvTol - Default = 1e-8; See link for more specifications.\nFeasib_Tol All constraints must be satisfied as per this tolerance. Note that this tolerance is absolute.\n CPLEX: CPX_PARAM_EPRHS - Default = 1e-6; See link for more specifications.\n Gurobi: FeasibilityTol - Default = 1e-6; See link for more specifications.\n clp: PrimalTolerance - Default = 1e-7; See link for more specifications.\n clp: DualTolerance - Default = 1e-7; See link for more specifications.\nOptimal_Tol Reduced costs must all be smaller than Optimal_Tol in the improving direction in order for a model to be declared optimal.\n CPLEX: CPX_PARAM_EPOPT - Default = 1e-6; See link for more specifications.\n Gurobi: OptimalityTol - Default = 1e-6; See link for more specifications.\nPre_Solve Controls the presolve level.\n Gurobi: Presolve - Default = -1; See link for more specifications.\n clp: PresolveType - Default = 5; See link for more specifications.\nCrossover Determines the crossover strategy used to transform the interior solution produced by barrier algorithm into a basic solution.\n CPLEX: CPX_PARAM_SOLUTIONTYPE - Default = 2; See link for more specifications.\n Gurobi: Crossover - Default = 0; See link for more specifications.\nNumericFocus Controls the degree to which the code attempts to detect and manage numerical issues.\n CPLEX: CPX_PARAM_NUMERICALEMPHASIS - Default = 0; See link for more specifications.\n Gurobi: NumericFocus - Default = 0; See link for more specifications.\nTimeLimit Time limit to terminate the solution algorithm, model could also terminate if it reaches MIPGap before this time.\n CPLEX: CPX_PARAM_TILIM- Default = 1e+75; See link for more specifications.\n Gurobi: TimeLimit - Default = infinity; See link for more specifications.\n clp: MaximumSeconds - Default = -1; See link for more specifications.\nMIPGap Optimality gap in case of mixed-integer program.\n CPLEX: CPX_PARAM_EPGAP- Default = 1e-4; See link for more specifications.\n Gurobi: MIPGap - Default = 1e-4; See link for more specifications.\nDualObjectiveLimit When using dual simplex (where the objective is monotonically changing), terminate when the objective exceeds this limit.\n clp: DualObjectiveLimit - Default = 1e308; See link for more specifications.\nMaximumIterations Terminate after performing this number of simplex iterations.\n clp: MaximumIterations - Default = 2147483647; See link for more specifications.\nLogLevel Set to 1, 2, 3, or 4 for increasing output. Set to 0 to disable output.\n clp: logLevel - Default = 1; See link for more specifications.\n cbc: logLevel - Default = 1; See link for more specifications.\nInfeasibleReturn Set to 1 to return as soon as the problem is found to be infeasible (by default, an infeasibility proof is computed as well).\n clp: InfeasibleReturn - Default = 0; See link for more specifications.\nScaling Sets or unsets scaling; 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 dynamic(later).\n clp: Scaling - Default = 3; See link for more specifications.\nPerturbation Perturbs problem; Switch on perturbation (50), automatic (100), don't try perturbing (102).\n clp: Perturbation - Default = 3; See link for more specifications.\nmaxSolutions Terminate after this many feasible solutions have been found.\n cbc: maxSolutions - Default = -1; See link for more specifications.\nmaxNodes Terminate after this many branch-and-bound nodes have been evaluated\n cbc: maxNodes - Default = -1; See link for more specifications.\nallowableGap Terminate after optimality gap is less than this value (on an absolute scale)\n cbc: allowableGap - Default = -1; See link for more specifications.\nratioGap Terminate after optimality gap is smaller than this relative fraction.\n cbc: ratioGap - Default = Inf; See link for more specifications.\nthreads Set the number of threads to use for parallel branch & bound.\n cbc: threads - Default = 1; See link for more specifications.","category":"page"},{"location":"Model_Reference/mga/#Modeling-to-Generate-Alternatives","page":"Modeling to Generate Alternatives","title":"Modeling to Generate Alternatives","text":"","category":"section"},{"location":"Model_Reference/mga/","page":"Modeling to Generate Alternatives","title":"Modeling to Generate Alternatives","text":"Modules = [GenX]\nPages = [\"modeling_to_generate_alternatives.jl\"]","category":"page"},{"location":"Model_Reference/mga/#GenX.mga-Tuple{JuMP.Model, AbstractString, Dict, Dict}","page":"Modeling to Generate Alternatives","title":"GenX.mga","text":"mga(EP::Model, path::AbstractString, setup::Dict, inputs::Dict)\n\nWe have implemented an updated Modeling to Generate Alternatives (MGA) Algorithm proposed by Berntsen and Trutnevyte (2017) to generate a set of feasible, near cost-optimal technology portfolios. This algorithm was developed by Brill Jr, E. D., 1979 and introduced to energy system planning by DeCarolia, J. F., 2011.\n\nTo create the MGA formulation, we replace the cost-minimizing objective function of GenX with a new objective function that creates multiple generation portfolios by zone. We further add a new budget constraint based on the optimal objective function value f^* of the least-cost model and the user-specified value of slack delta. After adding the slack constraint, the resulting MGA formulation is given as:\n\nbeginaligned\n\ttextmaxmin quad\n\tsum_z in mathcalZsum_r in mathcalR beta_zr^kP_zr\n\ttextst quad\n\tP_zr = sum_y in mathcalGsum_t in mathcalT omega_t Theta_ytzr \n\t f leq f^* + delta \n\tAx = b\nendaligned\n\nwhere, beta_zr is a random objective fucntion coefficient betwen 0100 for MGA iteration k. Theta_ytzr is a generation of technology y in zone z in time period t that belongs to a resource type r. We aggregate Theta_ytzr into a new variable P_zr that represents total generation from technology type r in a zone z. In the second constraint above, delta denote the increase in budget from the least-cost solution and f represents the expression for the total system cost. The constraint Ax = b represents all other constraints in the power system model. We then solve the formulation with minimization and maximization objective function to explore near optimal solution space.\n\n\n\n\n\n","category":"method"},{"location":"User_Guide/running_model/#Running-the-model","page":"Running the Model","title":"Running the model","text":"","category":"section"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"When running a new case, it is recommended to create a new folder for the case outside of the GenX repository. This folder should contain all the .csv input files described in the GenX Inputs section, as well as the settings folder containing at least the genx_settings.yml and [solver_name].yml files. ","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"tip: Tip\nCheck out the Running GenX for additional information on how to run GenX and what happens when you run a case.","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"Once the model and the solver are set up, and once all the .csv input files are ready, GenX can be run using the following command:","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"$ julia --project=/path/to/GenX\n\njulia> using GenX\njulia> run_genx_case!(\"/path/to/case\")","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case. ","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"Alternatively, you can create a Run.jl file with the following code:","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"using GenX\nrun_genx_case!(dirname(@__FILE__))","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"and and place it in the case folder. Then, you can run the case by opening a terminal and running the following command:","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"$ julia --project=\"/path/to/GenX\" /path/to/case/Run.jl","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"where /path/to/GenX is the path to the GenX repository, and /path/to/case is the path to the folder of the case.","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"The output files will be saved in the Results folder inside the case folder. Check out the GenX Outputs section for more information on the output files.","category":"page"},{"location":"User_Guide/running_model/","page":"Running the Model","title":"Running the Model","text":"note: Slack Variables\nTo run a case with slack variables, check out the Policy Slack Variables section.","category":"page"},{"location":"Model_Reference/Resources/long_duration_storage/#Long-Duration-Storage","page":"Long Duration Storage","title":"Long Duration Storage","text":"","category":"section"},{"location":"Model_Reference/Resources/long_duration_storage/","page":"Long Duration Storage","title":"Long Duration Storage","text":"Modules = [GenX]\nPages = [\"long_duration_storage.jl\"]","category":"page"},{"location":"Model_Reference/Resources/long_duration_storage/#GenX.long_duration_storage!-Tuple{JuMP.Model, Dict, Dict}","page":"Long Duration Storage","title":"GenX.long_duration_storage!","text":"long_duration_storage!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates variables and constraints enabling modeling of long duration storage resources when modeling representative time periods.\n Storage inventory balance at beginning of each representative period The constraints in this section are used to approximate the behavior of long-duration energy storage technologies when approximating annual grid operations by modeling operations over representative periods. Previously, the state of charge balance for storage (as defined in storage_all()) assumed that state of charge at the beginning and end of each representative period has to be the same. In other words, the amount of energy built up or consumed by storage technology o in zone z over the representative period m, Delta Q_ozm = 0. This assumption implicitly excludes the possibility of transferring energy from one representative period to the other which could be cost-optimal when the capital cost of energy storage capacity is relatively small. To model long-duration energy storage using representative periods, we replace the state of charge equation, such that the first term on the right hand side accounts for change in storage inventory associated with representative period m (Delta Q_ozm), which could be positive (net accumulation) or negative (net reduction).\n\nbeginaligned\n Gamma_oz(m-1)times tau^period+1 =left(1-eta_oz^lossright)times left(Gamma_ozmtimes tau^period -Delta Q_ozmright) - \n frac1eta_oz^dischargeTheta_oz(m-1)times tau^period+1 + eta_oz^chargePi_oz(m-1)times tau^period+1 quad forall o in mathcalO^LDES z in mathcalZ m in mathcalM\nendaligned\n\nBy definition mathcalT^start=left(m-1right) times tau^period+1 m in mathcalM, which implies that this constraint is defined for all values of t in T^start. \nStorage inventory change input periods We need additional variables and constraints to approximate energy exchange between representative periods, while accounting for their chronological occurence in the original input time series data and the possibility that two representative periods may not be adjacent to each other (see Figure below). To implement this, we introduce a new variable Q_oz n that models inventory of storage technology o in O in zone z in each input period n in mathcalN. Additionally we define a function mapping, f n rightarrow m, that uniquely maps each input period n to its corresponding representative period m. This mapping is available as an output of the process used to identify representative periods (E.g. k-means clustering Mallapragada et al., 2018).\n\n(Image: Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations) Figure. Modeling inter-period energy exchange via long-duration storage when using representative period temporal resolution to approximate annual grid operations\n\nThe following two equations define the storage inventory at the beginning of each input period n+1 as the sum of storage inventory at begining of previous input period n plus change in storage inventory for that period. The latter is approximated by the change in storage inventory in the corresponding representative period, identified per the mapping f(n). If the input period is also a representative period, then a second constraint enforces that initial storage level estimated by the intra-period storage balance constraint should equal the initial storage level estimated from the inter-period storage balance constraints.\n\nbeginaligned\n Q_ozn+1 = Q_ozn + Delta Q_ozf(n)\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalN\nendaligned\n\nbeginaligned\n Q_ozn =Gamma_ozf(n)times tau^period - Delta Q_ozm\nquad forall o in mathcalO^LDES z in mathcalZ n in mathcalN^rep\nendaligned\n\nFinally, the next constraint enforces that the initial storage level for each input period n must be less than the installed energy capacity limit. This constraint ensures that installed energy storage capacity is consistent with the state of charge during both the operational time periods t during each sample period m as well as at the start of each chronologically ordered input period n in the full annual time series.\n\nbeginaligned\n Q_ozn leq Delta^total energy_oz\nquad forall n in mathcalN o in mathcalO^LDES\nendaligned\n\nIf the capacity reserve margin constraint is enabled, a similar set of constraints is used to track the evolution of the energy held in reserve across representative periods. The main linking constraint is as follows:\n\nbeginaligned\n Gamma^CRM_oz(m-1)times tau^period+1 =left(1-eta_oz^lossright)times left(Gamma^CRM_ozmtimes tau^period -Delta Q_ozmright) + \n frac1eta_oz^dischargeTheta^CRM_oz(m-1)times tau^period+1 - eta_oz^chargePi^CRM_oz(m-1)times tau^period+1 quad forall o in mathcalO^LDES z in mathcalZ m in mathcalM\nendaligned\n\nAll other constraints are identical to those used to track the actual state of charge, except with the new variables Q^CRM_ozn and Delta Q^CRM_ozn used in place of Q_ozn and Delta Q_ozn, respectively.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/retrofit/#Retrofit","page":"Retrofit","title":"Retrofit","text":"","category":"section"},{"location":"Model_Reference/Resources/retrofit/","page":"Retrofit","title":"Retrofit","text":"Modules = [GenX]\nPages = [\"retrofits.jl\"]","category":"page"},{"location":"Model_Reference/Resources/retrofit/#GenX.retrofit-Tuple{JuMP.Model, Dict}","page":"Retrofit","title":"GenX.retrofit","text":"retrofit(EP::Model, inputs::Dict)\n\nThis function defines the constraints for operation of retrofit technologies, including \t\tbut not limited to carbon capture and thermal energy storage.\n\nFor retrofittable source technologies y and retrofit technologies r in the same region z and retrofit cluster id, (i.e. y in RS(id) and r in RO(id)), the total retrofit capacity Omega_r that may be installed is constrained by the available retrofittable capacity P_y as well as the efficiency ef_r of the retrofit technology.\n\nbeginaligned\n sum_y in RS(id)P_y = sum_r in RO(id)fracOmega_ref_r quad quad quad quad forall id in RETROFIT\nendaligned\n\nwhere RETROFIT represents the set of all retrofit IDs (clusters) in the model.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/generate_model/#Generating-the-model","page":"Generate the Model","title":"Generating the model","text":"","category":"section"},{"location":"Model_Reference/generate_model/","page":"Generate the Model","title":"Generate the Model","text":"Modules = [GenX]\nPages = [\"generate_model.jl\"]","category":"page"},{"location":"Model_Reference/generate_model/#GenX.generate_model-Tuple{Dict, Dict, MathOptInterface.OptimizerWithAttributes}","page":"Generate the Model","title":"GenX.generate_model","text":"generate_model(setup::Dict,inputs::Dict,OPTIMIZER::MOI.OptimizerWithAttributes,modeloutput = nothing)\n\nThis function sets up and solves a constrained optimization model of electricity system capacity expansion and operation problem and extracts solution variables for later processing.\n\nIn addition to calling a number of other modules to create constraints for specific resources, policies, and transmission assets, this function initializes two key expressions that are successively expanded in each of the resource-specific modules: (1) the objective function; and (2) the zonal power balance expression. These two expressions are the only expressions which link together individual modules (e.g. resources, transmission assets, policies), which otherwise are self-contained in defining relevant variables, expressions, and constraints.\n\nObjective Function\n\nThe objective function of GenX minimizes total annual electricity system costs over the following six components shown in the equation below:\n\nbeginaligned\n\tsum_y in mathcalG sum_z in mathcalZ\n\tleft( (pi^INVEST_yz times overlineOmega^size_yz times Omega_yz)\n\t+ (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right) + notag \n\tsum_y in mathcalO sum_z in mathcalZ\n\tleft( (pi^INVESTenergy_yz times Omega^energy_yz)\n\t+ (pi^FOMenergy_yz times Delta^totalenergy_yz)right) + notag \n\tsum_y in mathcalO^asym sum_z in mathcalZ\n\tleft( (pi^INVESTcharge_yz times Omega^charge_yz)\n\t+ (pi^FOMcharge_yz times Delta^totalcharge_yz)right) + notag \n\t sum_y in mathcalG sum_z in mathcalZ sum_t in mathcalT left( omega_ttimes(pi^VOM_yz + pi^FUEL_yz)times Theta_yztright) + sum_y in mathcalO cup DF sum_z in mathcalZ sum_t in mathcalT left( omega_ttimespi^VOMcharge_yz times Pi_yztright) +notag \n\tsum_s in mathcalS sum_z in mathcalZ sum_t in mathcalTleft(omega_t times n_s^slope times Lambda_sztright) + sum_t in mathcalT left(omega_t times pi^unmet_rsv times r^unmet_tright) notag \n\tsum_y in mathcalH sum_z in mathcalZ sum_t in mathcalTleft(omega_t times pi^START_yz times chi_sztright) + notag \n\t sum_l in mathcalLleft(pi^TCAP_l times bigtriangleupvarphi^max_lright)\nendaligned\n\nThe first summation represents the fixed costs of generation/discharge over all zones and technologies, which refects the sum of the annualized capital cost, pi^INVEST_yz, times the total new capacity added (if any), plus the Fixed O&M cost, pi^FOM_yz, times the net installed generation capacity, overlineOmega^size_yz times Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe second summation corresponds to the fixed cost of installed energy storage capacity and is summed over only the storage resources. This term includes the sum of the annualized energy capital cost, pi^INVESTenergy_yz, times the total new energy capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed energy storage capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe third summation corresponds to the fixed cost of installed charging power capacity and is summed over only over storage resources with independent/asymmetric charge and discharge power components (mathcalO^asym). This term includes the sum of the annualized charging power capital cost, pi^INVESTcharge_yz, times the total new charging power capacity added (if any), plus the Fixed O&M cost, pi^FOM energy_yz, times the net installed charging power capacity, Delta^total_yz (e.g., existing capacity less retirements plus additions).\n\nThe fourth and fifth summations corresponds to the operational cost across all zones, technologies, and time steps. The fourth summation represents the sum of fuel cost, pi^FUEL_yz (if any), plus variable O&M cost, pi^VOM_yz times the energy generation/discharge by generation or storage resources (or demand satisfied via flexible demand resources, yinmathcalDF) in time step t, Theta_yzt, and the weight of each time step t, omega_t, where omega_t is equal to 1 when modeling grid operations over the entire year (8760 hours), but otherwise is equal to the number of hours in the year represented by the representative time step, t such that the sum of omega_t forall t in T = 8760, approximating annual operating costs. The fifth summation represents the variable charging O&M cost, pi^VOMcharge_yz times the energy withdrawn for charging by storage resources (or demand deferred by flexible demand resources) in time step t , Pi_yzt and the annual weight of time step t,omega_t.\n\nThe sixth summation represents the total cost of unserved demand across all segments s of a segment-wise price-elastic demand curve, equal to the marginal value of consumption (or cost of non-served energy), n_s^slope, times the amount of non-served energy, Lambda_yzt, for each segment on each zone during each time step (weighted by omega_t).\n\nThe seventh summation represents the total cost of not meeting hourly operating reserve requirements, where pi^unmet_rsv is the cost penalty per unit of non-served reserve requirement, and r^unmet_t is the amount of non-served reserve requirement in each time step (weighted by omega_t).\n\nThe eighth summation corresponds to the startup costs incurred by technologies to which unit commitment decisions apply (e.g. y in mathcalUC), equal to the cost of start-up, pi^START_yz, times the number of startup events, chi_yzt, for the cluster of units in each zone and time step (weighted by omega_t).\n\nThe last term corresponds to the transmission reinforcement or construction costs, for each transmission line in the model. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, pi^TCAP_l, times the additional transmission capacity variable, bigtriangleupvarphi^max_l. Note that fixed O\\&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.\n\nIn summary, the objective function can be understood as the minimization of costs associated with five sets of different decisions: (1) where and how to invest on capacity, (2) how to dispatch or operate that capacity, (3) which consumer demand segments to serve or curtail, (4) how to cycle and commit thermal units subject to unit commitment decisions, (5) and where and how to invest in additional transmission network capacity to increase power transfer capacity between zones. Note however that each of these components are considered jointly and the optimization is performed over the whole problem at once as a monolithic co-optimization problem.\n\nPower Balance\n\nThe power balance constraint of the model ensures that electricity demand is met at every time step in each zone. As shown in the constraint, electricity demand, D_tz, at each time step and for each zone must be strictly equal to the sum of generation, Theta_yzt, from thermal technologies (mathcalH), curtailable VRE (mathcalVRE), must-run resources (mathcalMR), and hydro resources (mathcalW). At the same time, energy storage devices (mathcalO) can discharge energy, Theta_yzt to help satisfy demand, while when these devices are charging, Pi_yzt, they increase demand. For the case of flexible demand resources (mathcalDF), delaying demand (equivalent to charging virtual storage), Pi_yzt, decreases demand while satisfying delayed demand (equivalent to discharging virtual demand), Theta_yzt, increases demand. Price-responsive demand curtailment, Lambda_szt, also reduces demand. Finally, power flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign in the below constraint. At the same time losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see Transmission section).\n\nbeginaligned\n\t sum_yin mathcalHTheta_yzt +sum_yin mathcalVRETheta_yzt +sum_yin mathcalMRTheta_yzt + sum_yin mathcalO(Theta_yzt-Pi_yzt) + notag\n\t sum_yin mathcalDF(-Theta_yzt+Pi_yzt) +sum_yin mathcalWTheta_yzt+ notag\n\t+ sum_sin mathcalSLambda_szt - sum_lin mathcalL(varphi^map_lz times Phi_lt) -frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot)) = D_zt\n\tforall zin mathcalZ t in mathcalT\nendaligned\n\nArguments\n\nsetup::Dict: Dictionary containing the settings for the model.\ninputs::Dict: Dictionary containing the inputs for the model.\nOPTIMIZER::MOI.OptimizerWithAttributes: The optimizer to use for solving the model.\n\nReturns\n\nModel: The model object containing the entire optimization problem model to be solved by solve_model.jl\n\n\n\n\n\n","category":"method"},{"location":"Model_Concept_Overview/model_introduction/#GenX-Model-Introduction","page":"Model Introduction","title":"GenX Model Introduction","text":"","category":"section"},{"location":"Model_Concept_Overview/model_introduction/#Introduction","page":"Model Introduction","title":"Introduction","text":"","category":"section"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"GenX allows for the simultaneous co-optimization of several interlinked power system decision layers, described below:","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Capacity expansion planning (e.g., investment and retirement decisions for a full range of centralized and distributed generation, storage, and demand-side resources)\nHourly dispatch of generation, storage, and demand-side resources,\nUnit commitment decisions and operational constraints for thermal generators,\nCommitment of generation, storage, and demand-side capacity to meet system operating reserves requirements,\nCommitment of generation, storage, and demand-side capacity to meet capacity reserve requirements,\nTransmission network power flows (including losses) and network expansion decisions, and\nSeveral optional policy constraints","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Depending on the dimensionality of the problem, it may not be possible to model all decision layers at the highest possible resolution of detail, so the GenX model is designed to be highly configurable, allowing the user to specify the level of detail or abstraction along each of these layers or to omit one or more layers from consideration entirely.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"For example, while investment and dispatch decisions (Layers 1 and 2) are a consistent feature of the model under all configurations, the user has several options with regards to representing the operational constraints on various thermal power plants (e.g., coal, gas, nuclear, and biomass generators). Unit commitment (e.g., start-up and shut-down) decisions Morales-España et al., 2013 (Layer 3) can be modeled at the individual power plant level (as per De Sisternes Jimenez, 2014); by using an efficient clustering of similar or identical units (as per Palmintier, 2011, Palmintier, 2013, Palmintier, 2014); by using a linear relaxation (or convex hull) of the integer unit commitment constraints set; or ignoring unit commitment decisions entirely and treating generator output as fully continuous. Furthermore, different levels of resolution can be selected for each individual resource type, as desired (e.g., larger thermal units can be represented with integer unit commitment decisions while smaller units can be treated as fully continuous). In such a manner, the model can be configured to represent operating constraints on thermal generators at a level of resolution that achieves a desired balance between abstraction error and computational tractability and provides sufficient accuracy to generate insights for the problem at hand.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"The model can also be configured to consider commitment of capacity to supply frequency regulation (symmetric up and down) and operating reserves (up) needed by system operators to robustly resolve short-term uncertainty in demand and renewable energy forecasts and power plant or transmission network failures (Layer 4). Alternatively, reserve commitments can be ignored if desired.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Additionally, the model can approximate resource adequacy requirements through capacity reserve margin requirements at the zonal and/or system level (Layer 5). In this way, the model can approximate varying structure of capacity markets seen in deregulated electricity markets in the U.S. and other regions.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"The model also allows for transmission networks to be represented at several levels of detail (Layer 6) including at a zonal level with transport constraints on power flows between zones (as per Mai et al., 2013, Johnston et al., 2013, Hirth, 2017); or as a single zone problem where transmission constraints and flows are ignored. (A DC optimal power flow formulation is in development.) In cases where a nodal or zonal transmission model is employed, network capacity expansion decisions can be modeled or ignored, and transmission losses can be represented either as a linear function of power flows or a piecewise linear approximation of a quadratic function of power flows between nodes or zones (as per Zhang et al., 2013, Fitiwi et al., 2016), with the number of segments in the piecewise approximation specified by the user as desired. In a multi-zonal or nodal configuration, GenX can therefore consider siting generators in different locations, including balancing tradeoffs between access to different renewable resource quality, siting restrictions, and impacts on network congestions, power flows and losses.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"GenX also allows the user to specify several optional public policy constraints, such as CO2 emissions limits, minimum energy share requirements (such as renewable portfolio standard or clean energy standard policies), and minimum technology capacity requirements (e.g. technology deployment mandates).","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"Finally, the model is usually configured to consider a full year of operating decisions at an hourly resolution, but as this is often not tractable when considering large-scale problems with high resolution in other dimensions, GenX is also designed to model a number of subperiods – typically multiday periods of chronologically sequential hourly operating decisions – that can be selected via appropriate statistical clustering methods to represent a full year of operations (De Sisternes Jimenez and Webster, 2013, De Sisternes Jimenez, 2014, Poncelet et al., 2016, Nahmmacher et al., 2016, Blanford et al., 2016, Merrick, 2016, Mallapragada et al., 2018). GenX ships with a built-in time-domain reduction package that uses k-means or k-medoids to cluster raw time series data for demand (load) profiles and resource capacity factor profiles into representative periods during the input processing stage of the model. This method can also consider extreme points in the time series to capture noteworthy periods or periods with notably poor fits.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"With appropriate configuration of the model, GenX thus allows the user to tractably consider several interlinking decision layers in a single, monolithic optimization problem that would otherwise have been necessary to solve in different separated stages or models. The following figure reflects the range of configurations currently possible along the three key dimensions of chronological detail, operational detail, and network detail.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"(Image: Range of configurations currently implemented in GenX along three key dimensions of model resolution) Figure. Range of configurations currently implemented in GenX along three key dimensions of model resolution","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"The model can be configured to consider a single future planning year or multiple planning stages (or investment periods) in sequence. ","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"In single-stage planning mode, the model formulation is static, in the sense that its objective is not to determine when investments should take place over time, but rather to produce a snapshot of the minimum-cost generation capacity mix to meet demand at least cost under some pre-specified future conditions. \nThe user can formulate and solve a deterministic multi-stage planning problem with perfect foresight i.e. demand, cost, and policy assumptions about all stages are known and exploited to determine the least-cost investment trajectory for the entire period. The solution of this multi-stage problem relies on exploiting the decomposable nature of the multi-stage problem via the implementation of the dual dynamic programming algorithm, described in Lara et al. 2018 here. \nThe user can formulate a sequential, myopic multi-stage planning problem, where the model solves a sequence of single-stage investment planning problems wherein investment decisions in each stage are individually optimized to meet demand given assumptions for the current planning stage and with investment decisions from previous stages treated as inputs for the current stage. We refer to this as \"myopic\" (or shortsighted) mode since the solution does not account for information about future stages in determining investments for a given stage. This version is generally more computationally efficient than the deterministic multi-stage expansion with perfect foresight mode.","category":"page"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"More information on the two sequential, multi-stage planning modes can be found in the section on Multi-stage under the Model function reference tab. ","category":"page"},{"location":"Model_Concept_Overview/model_introduction/#Uses","page":"Model Introduction","title":"Uses","text":"","category":"section"},{"location":"Model_Concept_Overview/model_introduction/","page":"Model Introduction","title":"Model Introduction","text":"From a centralized planning perspective, the GenX model can help to determine the investments needed to supply future electricity demand at minimum cost, as is common in least-cost utility planning or integrated resource planning processes. In the context of liberalized markets, the model can be used by regulators and policy makers for indicative energy planning or policy analysis in order to establish a long-term vision of efficient market and policy outcomes. The model can also be used for techno-economic assessment of emerging electricity generation, storage, and demand-side resources and to enumerate the effect of parametric uncertainty (e.g., technology costs, fuel costs, demand, policy decisions) on the system-wide value or role of different resources.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Tutorial-4:-Model-Generation","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"To run GenX, we use the file Run.jl. This file will solve the optimization problem and generate the output files as described in the documentation and previous tutorial. It does so by first generating the model, then solving the model, both according to settings described in genx_settings.yml. However, Run.jl only contains one commmand, run_genx_case!(dirname(@__FILE__)). This can be confusing for users viewing the files for the first time. In reality, this function signals many more functions to run, generating and solving the model. This tutorial explains how the model in GenX is generated. The next tutorial will then describe how it is solved.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"We'll start by explaining JuMP, the optimization package that GenX uses to generate and solve the model.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Table-of-Contents","page":"Tutorial 4: Model Generation","title":"Table of Contents","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"JuMP\nGenerate Model\nArguments\nRun generate_model","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"JuMP is a modeling language for Julia. It allows users to create models for optimization problems, define variables and constraints, and apply a variety of solvers for the model. ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"GenX is a Linear Program (LP), which is a form of optimization problem in which a linear objective is minimized (or maximized) according to a set of linear constraints. For more information on LPs, see Wikipedia.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"using JuMP\nusing HiGHS","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Let's say we want to build a power grid consisting of and coal and wind plants. We want to decrease the cost of producing energy while still meeting a certain emissions threshold and full grid demand. Coal plants are cheaper to build and run but have higher emissions than wind farms. To find the minimum cost of a power grid meeting these constraints, we construct an LP using JuMP.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"beginaligned\n min 10 x + 15 y textObjective function (cost) \n textst \n x + y geq 10 textGrid Demand\n 55x + 70y leq 1000 textConstruction constraint\n 40 x + 5 y leq 200 textEmissions constraint \n x y geq 0 textNon-negativity constraints\nendaligned","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The core of the JuMP model is the function Model(), which creates the structure of our LP. Model() takes an optimizer as its input.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"power = Model(HiGHS.Optimizer)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"A JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: EMPTY_OPTIMIZER\nSolver name: HiGHS","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The model needs variables, defined using the JuMP function @variable:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@variable(power,x) # Coal\n@variable(power,y) # Wind","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Using the JuMP function @constraint, we can add the constraints of the model:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@constraint(power, non_neg_x, x >= 0) # Non-negativity constraint (can't have negative power plants!)\n@constraint(power, non_neg_y, y >= 0) # Non-negativity constraint\n\n@constraint(power, emissions, 40x + 5y <= 200) # Emisisons constraint\n@constraint(power, construction_costs, 55x + 70y <= 1000) # Cost of constructing a new plant\n\n@constraint(power, demand, x + y >= 10) # Grid demand","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"x + y geq 10","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Next, the function @expression defines an expression that can be used in either a constraint or objective function. In GenX, expressions are defined throughout the model generation and put into constraints and the objective function later.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@expression(power,objective,10x+15y)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"$ 10 x + 15 y $","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Finally, we define the objective function itself:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@objective(power, Min, objective)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"10 x + 15 y","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Our model is now set up! ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"print(power)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"beginaligned\nminquad 10 x + 15 y\ntextSubject to quad x geq 0\n y geq 0\n x + y geq 10\n 40 x + 5 y leq 200\n 55 x + 70 y leq 1000\nendaligned ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"In the next Tutorial, we go over how to use JuMP to solve the model we've constructed.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"When Run.jl is called, the model for GenX is constructed in a similar way, but with many more factors to consider. The next section goes over how the GenX model is constructed before it is solved.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Generate-Model","page":"Tutorial 4: Model Generation","title":"Generate Model","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The basic structure of the way Run.jl generates and solves the model is as follows:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The function run_genx_case(case) takes the \"case\" as its input. The case is all of the input files and settings found in the same folder as Run.jl. For example, in example_systems/1_three_zones, the case is:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Run_genx_case defines the setup, which are the settings in genx_settings.yml. From there, either run_genx_case_simple(case, mysetup) orrun_genx_case_multistage(case, mysetup) is called. Both of these define the inputs and optimizer. The optimizer is the solver as specified in genx_settings.yml, and the inputs are a variety of parameters specified by the settings and csv files found in the folder. Both of these functions then call generate_model(mysetup, myinputs, OPTIMIZER), which is the main subject of this tutorial.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"As in the above example, generate_model utilizes the JuMP functions Model(), @expression, @variable, and @constraints to form a model. This section goes through generate_model and explains how the expressions are formed to create the model.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Arguments","page":"Tutorial 4: Model Generation","title":"Arguments","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Generate_model takes three arguments: setup, inputs, and optimizer:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"To generate the arguments, we have to set a case path (this is set automatically when Run.jl is called):","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"using GenX","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"case = joinpath(\"example_systems/1_three_zones\") ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" \"example_systems/1_three_zones\"","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Setup includes the settings from genx_settings.yml along with the default settings found in configure_settings.jl. The function configure_settings combines the two.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"genx_settings = GenX.get_settings_path(case, \"genx_settings.yml\") # Settings YAML file path\nwriteoutput_settings = GenX.get_settings_path(case, \"output_settings.yml\") # Set output path\nsetup = GenX.configure_settings(genx_settings,writeoutput_settings) # Combines genx_settings with defaults","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Configuring Settings\n Dict{Any, Any} with 24 entries:\n \"NetworkExpansion\" => 0\n \"TimeDomainReductionFolder\" => \"TDR_Results\"\n \"EnableJuMPStringNames\" => false\n \"Trans_Loss_Segments\" => 1\n \"ModelingtoGenerateAlternativeSlack\" => 0.1\n \"Solver\" => \"HiGHS\"\n \"Reserves\" => 0\n \"MultiStage\" => 0\n \"OverwriteResults\" => 0\n \"ModelingToGenerateAlternatives\" => 0\n \"MaxCapReq\" => 1\n \"MinCapReq\" => 1\n \"CO2Cap\" => 2\n \"WriteShadowPrices\" => 1\n \"ModelingToGenerateAlternativeIterations\" => 3\n \"ParameterScale\" => 1\n \"EnergyShareRequirement\" => 1\n \"PrintModel\" => 0\n \"TimeDomainReduction\" => 1\n \"CapacityReserveMargin\" => 1\n \"MethodofMorris\" => 0\n \"StorageLosses\" => 1\n \"IncludeLossesInESR\" => 0\n \"UCommit\" => 2","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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. As a reminder, TDR_results is not overwritten when called again. The cell below will delete a preexisting TDR_results folder if it is there.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"TDRpath = joinpath(case, setup[\"TimeDomainReductionFolder\"])\nsystem_path = joinpath(case, setup[\"SystemFolder\"])\n\nsettings_path = GenX.get_settings_path(case)\n\nif \"TDR_results\" in cd(readdir,case)\n rm(joinpath(case,\"TDR_results\"), recursive=true) \nend\n\nif setup[\"TimeDomainReduction\"] == 1\n GenX.prevent_doubled_timedomainreduction(system_path)\n if !GenX.time_domain_reduced_files_exist(TDRpath)\n println(\"Clustering Time Series Data (Grouped)...\")\n GenX.cluster_inputs(case, settings_path, setup)\n else\n println(\"Time Series Data Already Clustered.\")\n end\nend","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Clustering Time Series Data (Grouped)...\n Reading Input CSV Files\n Network.csv Successfully Read!\n Load_data.csv Successfully Read!\n Fuels_data.csv Successfully Read!\n Generators_data.csv Successfully Read!\n Generators_variability.csv Successfully Read!\n Validating time basis\n Capacity_reserve_margin.csv Successfully Read!\n Minimum_capacity_requirement.csv Successfully Read!\n Maximum_capacity_requirement.csv Successfully Read!\n Energy_share_requirement.csv Successfully Read!\n CO2_cap.csv Successfully Read!\n CSV Files Successfully Read In From Example_Systems_Tutorials/SmallNewEngland/OneZone\n\n Dict{String, Any} with 9 entries:\n \"RMSE\" => Dict(\"Load_MW_z1\"=>1100.54, \"NG\"=>0.312319, \"onshore_wind_…\n \"OutputDF\" => DataFrame…\n \"ColToZoneMap\" => Dict(\"Load_MW_z1\"=>1, \"battery_z1\"=>1, \"natural_gas_combin…\n \"ClusterObject\" => KmeansResult{Matrix{Float64}, Float64, Int64}([-1.38728 -1…\n \"TDRsetup\" => Dict{Any, Any}(\"IterativelyAddPeriods\"=>1, \"ExtremePeriods…\n \"Assignments\" => [1, 1, 1, 1, 2, 2, 2, 2, 2, 3 … 6, 4, 3, 5, 5, 9, 10, 10…\n \"InputDF\" => [672×49 DataFrame\n \"Weights\" => [673.846, 1010.77, 673.846, 842.308, 842.308, 1853.08, 185…\n \"Centers\" => Any[1, 7, 12, 15, 23, 24, 28, 29, 48, 50, 51]","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The optimizer argument is taken from setup:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"OPTIMIZER = GenX.configure_solver(settings_path,HiGHS.Optimizer)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The function configure_solver converts the string from \"Solver\" to a MathOptInterface optimizer so it can be used in the JuMP model as the optimizer. It also goes into the settings file for the specified solver (in this case HiGHS, so 1_three_zones/settings/highs_settings.yml) and uses the settings to configure the solver to be used later.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"typeof(OPTIMIZER)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" MathOptInterface.OptimizerWithAttributes","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The \"inputs\" argument is generated by the function load_inputs from the case in run_genx_case_simple (or multistage). If TDR is set to 1 in the settings file, then load_inputs will draw some of the files from the TDR_Results folder. TDR_Results is produced when the case is run. ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"inputs = GenX.load_inputs(setup, case)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Reading Input CSV Files\n Network.csv Successfully Read!\n Load_data.csv Successfully Read!\n Fuels_data.csv Successfully Read!\n Generators_data.csv Successfully Read!\n Generators_variability.csv Successfully Read!\n Validating time basis\n Capacity_reserve_margin.csv Successfully Read!\n Minimum_capacity_requirement.csv Successfully Read!\n Maximum_capacity_requirement.csv Successfully Read!\n Energy_share_requirement.csv Successfully Read!\n CO2_cap.csv Successfully Read!\n CSV Files Successfully Read In From Example_Systems_Tutorials/SmallNewEngland/OneZone\n\n Dict{Any, Any} with 66 entries:\n \"Z\" => 1\n \"LOSS_LINES\" => [1]\n \"RET_CAP_CHARGE\" => Int64[]\n \"pC_D_Curtail\" => [50.0]\n \"dfGen\" => [4×68 DataFram\n \"pTrans_Max_Possible\" => [2.95]\n \"pNet_Map\" => [1.0;;]\n \"omega\" => [4.01099, 4.01099, 4.01099, 4.01099, 4.01099, 4.0109…\n \"RET_CAP_ENERGY\" => [4]\n \"RESOURCES\" => String31[\"natural_gas_combined_cycle\", \"solar_pv\", \"…\n \"COMMIT\" => [1]\n \"pMax_D_Curtail\" => [1]\n \"STOR_ALL\" => [4]\n \"THERM_ALL\" => [1]\n \"dfCO2CapZones\" => [1;;]\n \"REP_PERIOD\" => 11\n \"MinCapReq\" => [5.0, 10.0, 6.0]\n \"STOR_LONG_DURATION\" => Int64[]\n \"dfCapRes\" => [0.156;;]\n \"STOR_SYMMETRIC\" => [4]\n \"VRE\" => [2, 3]\n \"RETRO\" => Int64[]\n \"THERM_COMMIT\" => [1]\n \"TRANS_LOSS_SEGS\" => 1\n \"H\" => 168\n ⋮ => ⋮","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Now that we have our arguments, we're ready to generate the model itself.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/#Run-generate_model","page":"Tutorial 4: Model Generation","title":"Run generate_model","text":"","category":"section"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"This subsection replicates the arguments in the function generate_model. Note: Running some of these cells for a second time will throw an error as the code will attempt to define a new expression with the name of an existing expression. To run the Tutorial again, clear and restart the kernel.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"First, we initialize a model and define the time step and zone variables","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"EP = Model(OPTIMIZER) # From JuMP","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"A JuMP Model\nFeasibility problem with:\nVariables: 0\nModel mode: AUTOMATIC\nCachingOptimizer state: EMPTY_OPTIMIZER\nSolver name: HiGHS","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"T = inputs[\"T\"]; # Number of time steps (hours)\nZ = inputs[\"Z\"]; # Number of zones","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Next, the dummy variable vZERO, the objective function, the power balance expression, and zone generation expression are all initialized to zero:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Introduce dummy variable fixed to zero to ensure that expressions like eTotalCap,\n# eTotalCapCharge, eTotalCapEnergy and eAvail_Trans_Cap all have a JuMP variable\n\nGenX.set_string_names_on_creation(EP, Bool(setup[\"EnableJuMPStringNames\"]))\n@variable(EP, vZERO == 0);\n\n# Initialize Power Balance Expression\n# Expression for \"baseline\" power balance constraint\nGenX.create_empty_expression!(EP, :ePowerBalance, (T, Z))\n\n# Initialize Objective Function Expression\nEP[:eObj] = AffExpr(0.0)\n\nGenX.create_empty_expression!(EP, :eGenerationByZone, (Z, T))\n\n# Energy losses related to technologies\nGenX.create_empty_expression!(EP, :eELOSSByZone, Z)","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" 1×1848 Matrix{Int64}:\n 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","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Initialize Capacity Reserve Margin Expression\nif setup[\"CapacityReserveMargin\"] > 0\n GenX.create_empty_expression!(EP, :eCapResMarBalance, (inputs[\"NCapacityReserveMargin\"], T))\nend\n\n# Energy Share Requirement\nif setup[\"EnergyShareRequirement\"] >= 1\n GenX.create_empty_expression!(EP, :eESR, inputs[\"nESR\"])\nend\n\nif setup[\"MinCapReq\"] == 1\n GenX.create_empty_expression!(EP, :eMinCapRes, inputs[\"NumberOfMinCapReqs\"])\nend\n\nif setup[\"MaxCapReq\"] == 1\n GenX.create_empty_expression!(EP, :eMaxCapRes, inputs[\"NumberOfMaxCapReqs\"])\nend","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The other settings will be used later on.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Infrastructure\nGenX.discharge!(EP, inputs, setup)\n\nGenX.non_served_energy!(EP, inputs, setup)\n\nGenX.investment_discharge!(EP, inputs, setup)\n\nif setup[\"UCommit\"] > 0\n GenX.ucommit!(EP, inputs, setup)\nend\n\nGenX.fuel!(EP, inputs, setup)\n\nGenX.co2!(EP, inputs) \n\nif setup[\"OperationalReserves\"] > 0\n GenX.operational_reserves!(EP, inputs, setup)\nend\n\nif Z > 1\n GenX.investment_transmission!(EP, inputs, setup)\n GenX.transmission!(EP, inputs, setup)\nend\n\nif Z > 1 && setup[\"DC_OPF\"] != 0\n GenX.dcopf_transmission!(EP, inputs, setup)\nend","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Discharge Module\n Non-served Energy Module\n Investment Discharge Module\n Unit Commitment Module\n Fuel Module\n CO2 Module\n Investment Transmission Module\n Transmission Module","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Technologies\n# Model constraints, variables, expression related to dispatchable renewable resources\n\nif !isempty(inputs[\"VRE\"])\n GenX.curtailable_variable_renewable!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to non-dispatchable renewable resources\nif !isempty(inputs[\"MUST_RUN\"])\n GenX/must_run!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to energy storage modeling\nif !isempty(inputs[\"STOR_ALL\"])\n GenX.storage!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to reservoir hydropower resources\nif !isempty(inputs[\"HYDRO_RES\"])\n GenX.hydro_res!(EP, inputs, setup)\nend\n\nif !isempty(inputs[\"ELECTROLYZER\"])\n GenX.electrolyzer!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to reservoir hydropower resources with long duration storage\nif inputs[\"REP_PERIOD\"] > 1 && !isempty(inputs[\"STOR_HYDRO_LONG_DURATION\"])\n GenX.hydro_inter_period_linkage!(EP, inputs)\nend\n\n# Model constraints, variables, expression related to demand flexibility resources\nif !isempty(inputs[\"FLEX\"])\n GenX.flexible_demand!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expression related to thermal resource technologies\nif !isempty(inputs[\"THERM_ALL\"])\n GenX.thermal!(EP, inputs, setup)\nend\n\n# Model constraints, variables, expressions related to the co-located VRE-storage resources\nif !isempty(inputs[\"VRE_STOR\"])\n GenX.vre_stor!(EP, inputs, setup)\nend\n\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Finally, we define expressions and variables using policies outlined in the inputs. These functions can be found in src/policies and in the Emission mitigation policies section of the documentation:","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"# Policies\n\nif setup[\"OperationalReserves\"] > 0\n GenX.operational_reserves_constraints!(EP, inputs)\nend\n\n# CO2 emissions limits\nif setup[\"CO2Cap\"] > 0\n GenX.co2_cap!(EP, inputs, setup)\nend\n\n# Endogenous Retirements\nif setup[\"MultiStage\"] > 0\n GenX.endogenous_retirement!(EP, inputs, setup)\nend\n\n# Energy Share Requirement\nif setup[\"EnergyShareRequirement\"] >= 1\n GenX.energy_share_requirement!(EP, inputs, setup)\nend\n\n#Capacity Reserve Margin\nif setup[\"CapacityReserveMargin\"] > 0\n GenX.cap_reserve_margin!(EP, inputs, setup)\nend\n\nif (setup[\"MinCapReq\"] == 1)\n GenX.minimum_capacity_requirement!(EP, inputs, setup)\nend\n\nif setup[\"MaxCapReq\"] == 1\n GenX.maximum_capacity_requirement!(EP, inputs, setup)\nend\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" Energy Share Requirement Policies Module\n Capacity Reserve Margin Policies Module\n Minimum Capacity Requirement Module\n Maximum Capacity Requirement Module\n\n 3-element Vector{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}, ScalarShape}}:\n cZoneMaxCapReq[1] : -vRETCAP[2] + vCAP[2] ≤ 50\n cZoneMaxCapReq[2] : -vRETCAP[3] + vCAP[3] ≤ 100\n cZoneMaxCapReq[3] : -vRETCAP[4] + vCAP[4] ≤ 60\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The expressions and variables for the model have all been defined! All that's left to do is define the constraints and objective function.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"The Objective Function here is to minimize ","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"@objective(EP,Min,EP[:eObj])","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"0.17159171428571432 vP_{1,1} + 0.0004010989010989012 vP_{3,1} + 0.0006016483516483517 vP_{4,1} + 0.17159171428571432 vP_{1,2} + 0.0004010989010989012 vP_{3,2} + 0.0006016483516483517 vP_{4,2} + 0.17159171428571432 vP_{1,3} + 0.0004010989010989012 vP_{3,3} + 0.0006016483516483517 vP_{4,3} + 0.17159171428571432 vP_{1,4} + 0.0004010989010989012 vP_{3,4} + 0.0006016483516483517 vP_{4,4} + 0.17159171428571432 vP_{1,5} + 0.0004010989010989012 vP_{3,5} + 0.0006016483516483517 vP_{4,5} + 0.17159171428571432 vP_{1,6} + 0.0004010989010989012 vP_{3,6} + 0.0006016483516483517 vP_{4,6} + 0.17159171428571432 vP_{1,7} + 0.0004010989010989012 vP_{3,7} + 0.0006016483516483517 vP_{4,7} + 0.17159171428571432 vP_{1,8} + 0.0004010989010989012 vP_{3,8} + 0.0006016483516483517 vP_{4,8} + 0.17159171428571432 vP_{1,9} + 0.0004010989010989012 vP_{3,9} + 0.0006016483516483517 vP_{4,9} + 0.17159171428571432 vP_{1,10} + 0.0004010989010989012 vP_{3,10} + 0.0006016483516483517 vP_{4,10} + [[\\ldots\\text{11038 terms omitted}\\ldots]] + 0.00015041208791208792 vCHARGE_{4,1819} + 0.00015041208791208792 vCHARGE_{4,1820} + 0.00015041208791208792 vCHARGE_{4,1821} + 0.00015041208791208792 vCHARGE_{4,1822} + 0.00015041208791208792 vCHARGE_{4,1823} + 0.00015041208791208792 vCHARGE_{4,1824} + 0.00015041208791208792 vCHARGE_{4,1825} + 0.00015041208791208792 vCHARGE_{4,1826} + 0.00015041208791208792 vCHARGE_{4,1827} + 0.00015041208791208792 vCHARGE_{4,1828} + 0.00015041208791208792 vCHARGE_{4,1829} + 0.00015041208791208792 vCHARGE_{4,1830} + 0.00015041208791208792 vCHARGE_{4,1831} + 0.00015041208791208792 vCHARGE_{4,1832} + 0.00015041208791208792 vCHARGE_{4,1833} + 0.00015041208791208792 vCHARGE_{4,1834} + 0.00015041208791208792 vCHARGE_{4,1835} + 0.00015041208791208792 vCHARGE_{4,1836} + 0.00015041208791208792 vCHARGE_{4,1837} + 0.00015041208791208792 vCHARGE_{4,1838} + 0.00015041208791208792 vCHARGE_{4,1839} + 0.00015041208791208792 vCHARGE_{4,1840} + 0.00015041208791208792 vCHARGE_{4,1841} + 0.00015041208791208792 vCHARGE_{4,1842} + 0.00015041208791208792 vCHARGE_{4,1843} + 0.00015041208791208792 vCHARGE_{4,1844} + 0.00015041208791208792 vCHARGE_{4,1845} + 0.00015041208791208792 vCHARGE_{4,1846} + 0.00015041208791208792 vCHARGE_{4,1847} + 0.00015041208791208792 vCHARGE_{4,1848} $","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"Our constraint is the Power Balance, which is set here to have to meet the demand of the network. The demand is outlined in the last columns of Load_data.csv, and is set to inputs in from the load_load_data function within load_inputs, used in run_genx_case.","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"## Power balance constraints\n# demand = generation + storage discharge - storage charge - demand deferral + deferred demand satisfaction - demand curtailment (NSE)\n# + incoming power flows - outgoing power flows - flow losses - charge of heat storage + generation from NACC\n@constraint(EP, cPowerBalance[t=1:T, z=1:Z], EP[:ePowerBalance][t,z] == inputs[\"pD\"][t,z])\n","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":" 1848×1 Matrix{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}, ScalarShape}}:\n cPowerBalance[1,1] : vP[2,1] + vP[3,1] + vP[4,1] + vNSE[1,1,1] - vCHARGE[4,1] = 11.162\n cPowerBalance[2,1] : vP[2,2] + vP[3,2] + vP[4,2] + vNSE[1,2,1] - vCHARGE[4,2] = 10.556\n cPowerBalance[3,1] : vP[2,3] + vP[3,3] + vP[4,3] + vNSE[1,3,1] - vCHARGE[4,3] = 10.105\n cPowerBalance[4,1] : vP[2,4] + vP[3,4] + vP[4,4] + vNSE[1,4,1] - vCHARGE[4,4] = 9.878\n cPowerBalance[5,1] : vP[2,5] + vP[3,5] + vP[4,5] + vNSE[1,5,1] - vCHARGE[4,5] = 9.843\n cPowerBalance[6,1] : vP[2,6] + vP[3,6] + vP[4,6] + vNSE[1,6,1] - vCHARGE[4,6] = 10.017\n cPowerBalance[7,1] : vP[2,7] + vP[3,7] + vP[4,7] + vNSE[1,7,1] - vCHARGE[4,7] = 10.39\n cPowerBalance[8,1] : vP[2,8] + vP[3,8] + vP[4,8] + vNSE[1,8,1] - vCHARGE[4,8] = 10.727\n cPowerBalance[9,1] : vP[2,9] + vP[3,9] + vP[4,9] + vNSE[1,9,1] - vCHARGE[4,9] = 11.298\n cPowerBalance[10,1] : vP[2,10] + vP[3,10] + vP[4,10] + vNSE[1,10,1] - vCHARGE[4,10] = 11.859\n cPowerBalance[11,1] : vP[2,11] + vP[3,11] + vP[4,11] + vNSE[1,11,1] - vCHARGE[4,11] = 12.196\n cPowerBalance[12,1] : vP[2,12] + vP[3,12] + vP[4,12] + vNSE[1,12,1] - vCHARGE[4,12] = 12.321\n cPowerBalance[13,1] : vP[2,13] + vP[3,13] + vP[4,13] + vNSE[1,13,1] - vCHARGE[4,13] = 12.381\n ⋮\n cPowerBalance[1837,1] : vP[2,1837] + vP[3,1837] + vP[4,1837] + vNSE[1,1837,1] - vCHARGE[4,1837] = 13.911\n cPowerBalance[1838,1] : vP[2,1838] + vP[3,1838] + vP[4,1838] + vNSE[1,1838,1] - vCHARGE[4,1838] = 13.818\n cPowerBalance[1839,1] : vP[2,1839] + vP[3,1839] + vP[4,1839] + vNSE[1,1839,1] - vCHARGE[4,1839] = 13.71\n cPowerBalance[1840,1] : vP[2,1840] + vP[3,1840] + vP[4,1840] + vNSE[1,1840,1] - vCHARGE[4,1840] = 13.796\n cPowerBalance[1841,1] : vP[2,1841] + vP[3,1841] + vP[4,1841] + vNSE[1,1841,1] - vCHARGE[4,1841] = 15.038\n cPowerBalance[1842,1] : vP[2,1842] + vP[3,1842] + vP[4,1842] + vNSE[1,1842,1] - vCHARGE[4,1842] = 16.088\n cPowerBalance[1843,1] : vP[2,1843] + vP[3,1843] + vP[4,1843] + vNSE[1,1843,1] - vCHARGE[4,1843] = 16.076\n cPowerBalance[1844,1] : vP[2,1844] + vP[3,1844] + vP[4,1844] + vNSE[1,1844,1] - vCHARGE[4,1844] = 15.782\n cPowerBalance[1845,1] : vP[2,1845] + vP[3,1845] + vP[4,1845] + vNSE[1,1845,1] - vCHARGE[4,1845] = 15.392\n cPowerBalance[1846,1] : vP[2,1846] + vP[3,1846] + vP[4,1846] + vNSE[1,1846,1] - vCHARGE[4,1846] = 14.663\n cPowerBalance[1847,1] : vP[2,1847] + vP[3,1847] + vP[4,1847] + vNSE[1,1847,1] - vCHARGE[4,1847] = 13.62\n cPowerBalance[1848,1] : vP[2,1848] + vP[3,1848] + vP[4,1848] + vNSE[1,1848,1] - vCHARGE[4,1848] = 12.388","category":"page"},{"location":"Tutorials/Tutorial_4_model_generation/","page":"Tutorial 4: Model Generation","title":"Tutorial 4: Model Generation","text":"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.","category":"page"},{"location":"Model_Reference/Resources/storage_symmetric/#Storage-Symmetric","page":"Storage Symmetric","title":"Storage Symmetric","text":"","category":"section"},{"location":"Model_Reference/Resources/storage_symmetric/","page":"Storage Symmetric","title":"Storage Symmetric","text":"Modules = [GenX]\nPages = [\"storage_symmetric.jl\"]","category":"page"},{"location":"Model_Reference/Resources/storage_symmetric/#GenX.storage_symmetric!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Symmetric","title":"GenX.storage_symmetric!","text":"storage_symmetric!(EP::Model, inputs::Dict, setup::Dict)\n\nSets up variables and constraints specific to storage resources with symmetric charge and discharge capacities. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/storage_symmetric/#GenX.storage_symmetric_operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Storage Symmetric","title":"GenX.storage_symmetric_operational_reserves!","text":"storage_symmetric_operational_reserves!(EP::Model, inputs::Dict)\n\nSets up variables and constraints specific to storage resources with symmetric charge and discharge capacities when reserves are modeled. See storage() in storage.jl for description of constraints.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/maintenance_overview/#Optimized-Scheduled-Maintenance","page":"Maintenance","title":"Optimized Scheduled Maintenance","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Added in v0.4","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"In the real world, some types of resources (notably, fission) require regular scheduled maintenance, which often takes several weeks. During this time, the plant produces no power. This module allows GenX to find the best time of year for plants to undergo maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Scheduled maintenance is implemented only for thermal plants with unit commitment (THERM=1).","category":"page"},{"location":"Model_Reference/maintenance_overview/#Description-of-the-maintenance-model","page":"Maintenance","title":"Description of the maintenance model","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"A plant requires a single contiguous period of h ge 1 hours of maintenance, every y ge 1 years. For each plant, the best time to start the maintenance period is determined by the optimizer.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"During maintenance, the plant cannot be \"commited\", and therefore","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"uses no fuel,\nproduces no power,\nand does not contribute to reserves.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Additionally, ","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"the plant does not contribute to any Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Treatment-of-plants-that-require-maintenance-only-every-few-years","page":"Maintenance","title":"Treatment of plants that require maintenance only every few years","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"GenX models a long-term equilibrium, and each problem generally represents a single full year. If a plant requires maintenance every y years, we take the simplification that at least 1y of the plants must undergo maintenance in the modeled year.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"See also \"Interaction with integer unit commitment\" below.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Reduction-of-number-of-possible-start-dates","page":"Maintenance","title":"Reduction of number of possible start dates","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"This module creates constraints which work across long periods, and consequently can be very expensive to solve. In order to reduce the expense, the set of possible maintenance start dates can be limited. Rather than have maintenance potentially start every hour, one can have possible start dates which are once per day, once per week, etc. (In reality, maintenance is likely scheduled months in advance, so optimizing down to the hour may not be realistic anyway.)","category":"page"},{"location":"Model_Reference/maintenance_overview/#How-to-use","page":"Maintenance","title":"How to use","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"There are four columns which need to be added to the plant data, i.e. in Generators_data.csv:","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"MAINT should be 1 for plants that require maintenance and 0 otherwise.\nMaintenance_Duration is the number of hours the maintenance period lasts.\nMaintenance_Cycle_Length_Years. If 1, maintenance every year, if 3 maintenance every 3 years, etc.\nMaintenance_Begin_Cadence. Spacing between hours in which maintenance can start.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The last three fields must be integers which are greater than 0. They are ignored for any plants which do not require maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Maintenance_Duration must be less than the total number of hours in the year.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If Maintenance_Begin_Cadence is 1 then the maintenance can begin in any hour. If it is 168 then it can begin in hours 1, 169, 337, etc.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Restrictions-on-use","page":"Maintenance","title":"Restrictions on use","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The maintenance module has these restrictions:","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"More than a single maintenance period per year (i.e. every three months) is not possible in the current formulation.\nOnly full-year cases can be run; there must be only one \"representative period\".","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"It would not make sense to model a month-long maintenance period when the year is modeled as a series of representative weeks, for example.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Interaction-with-integer-unit-commitment","page":"Maintenance","title":"Interaction with integer unit commitment","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If integer unit commitment is on (UCommit=1) this module may not produce correct results; there may be more maintenance than the user wants. This is because the formulation specifies that the number of plants that go down for maintenance in the simulated year must be at least (the number of plants in the zone)/(the maintenance cycle length in years). As a reminder, the number of plants is eTotalCap / Cap_Size.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If there were three 500 MW plants (total 1500 MW) in a zone, and they require maintenance every three years (Maintenance_Cycle_Length_Years=3), the formulation will work properly: one of the three plants will go under maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"But if there was only one 500 MW plant, and it requires maintenance every 3 years, the constraint will still make it do maintenance every year, because ceil(1/3) is 1. The whole 500 MW plant will do maintenance. This is the unexpected behavior.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"However, if integer unit commitment was relaxed to \"linearized\" unit commitment (UCommit=2), the model will have only 500 MW / 3 = 166.6 MW worth of this plant do maintenance.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Hint:-pre-scheduling-maintenance","page":"Maintenance","title":"Hint: pre-scheduling maintenance","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If you want to pre-schedule when maintenance occurs, you might not need this module. Instead, you could set the maximum power output of the plant to zero for a certain period, or make its fuel extremely expensive during that time. However, the plant would still be able to contribute to the Capacity Reserve Margin.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Outputs-produced","page":"Maintenance","title":"Outputs produced","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"If at least one plant has MAINT=1, a file maint_down.csv will be written listing how many plants are down for maintenance in each timestep.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Notes-on-mathematical-formulation","page":"Maintenance","title":"Notes on mathematical formulation","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The formulation of the maintenance state is very similar to the formulation of unit commitment.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"There is a variable called something like vMSHUT which is analogous to vSTART and controls the start of the maintenance period. There is another variable called something like vMDOWN analogous to vCOMMIT which controls the maintenance status in any hour.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"A constraint ensures that the value of vMDOWN in any hour is always more than the number of vMSHUTs in the previous Maintenance_Duration hours.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"Another constraint ensures that the number of plants committed (vCOMMIT) at any one time plus the number of plants under maintenance (vMDOWN) is less than the total number of plants.","category":"page"},{"location":"Model_Reference/maintenance_overview/#Developer-note:-adding-maintenance-to-a-resource","page":"Maintenance","title":"Developer note: adding maintenance to a resource","text":"","category":"section"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The maintenance formulation is applied on a per-resource basis, by calling the function GenX.maintenance_formulation!. ","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"See GenX.maintenance_formulation_thermal_commit! for an example of how to apply it to a new resource.","category":"page"},{"location":"Model_Reference/maintenance_overview/","page":"Maintenance","title":"Maintenance","text":"The resource must have a vCOMMIT-like variable which is proportional to maximum the power output, etc at any given timestep.\nThe resource must have a eTotalCap-like quantity and a Cap_Size-like parameter; only the ratio of the two is used.","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/#Tutorial-2:-Network-Visualization","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"","category":"section"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"Interactive Notebook of the tutorial","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"To run GenX, there are five mandatory input files: Fuels_data.csv, Network.csv, Load_data.csv, Generators_variability.csv, and Generators_data.csv. Detailed descriptions of these files can be found in the GenX Inputs page of the documentation. This tutorial helps visualize the file Network.csv using the example system example_systems/1_three_zones.","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"using CSV\nusing DataFrames","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"The input file Network.csv contains the nodes of your network, how they connect to each other, and some important features about them. Below is the network file for example_systems/1_three_zones:","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"network = CSV.read(\"example_systems/1_three_zones/system/Network.csv\",DataFrame,missingstring=\"NA\")","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"
3×14 DataFrame
RowColumn1Network_zonesNetwork_LinesStart_ZoneEnd_ZoneLine_Max_Flow_MWtransmission_path_namedistance_mileLine_Loss_PercentageLine_Max_Reinforcement_MWLine_Reinforcement_Cost_per_MWyrDerateCapRes_1CapRes_1CapRes_Excl_1
String3String3String3String3String3String7String15String15String15String7String7String7String3Int64?
1MAz11122950MA_to_CT123.05840.0123058372950120600.9500
2CTz22132000MA_to_ME196.53850.0196538472000192610.9500
3MEz3missing
","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"MA, CT, and ME are the abbreviations for states Massachusetts, Connecticut, and Maine. However, since the US region of New England contains other states as well, MA in this case is also used to refer to those states.","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"Columns Start_Zone and End_Zone specify the network of the three regions. In this case, there are only two network lines, specified in the Network_Lines columns. The Start_Zone column indicates that the first node, MA, is the source of both lines as both rows have value 1. Rows z1 and z2 have values of 2 and 3 in End_Zone, which means both nodes CT and ME recieve energy from node MA. This is also indicated in the column `transmissionpathname'. ","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"Below is a visualization of the network:","category":"page"},{"location":"Tutorials/Tutorial_2_network_visualization/","page":"Tutorial 2: Network Visualization","title":"Tutorial 2: Network Visualization","text":"","category":"page"},{"location":"Model_Reference/Resources/thermal_commit/#Thermal-Commit","page":"Thermal Commit","title":"Thermal Commit","text":"","category":"section"},{"location":"Model_Reference/Resources/thermal_commit/","page":"Thermal Commit","title":"Thermal Commit","text":"Modules = [GenX]\nPages = [\"thermal_commit.jl\"]","category":"page"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.maintenance_formulation_thermal_commit!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal Commit","title":"GenX.maintenance_formulation_thermal_commit!","text":"maintenance_formulation_thermal_commit!(EP::Model, inputs::Dict, setup::Dict)\n\nCreates maintenance variables and constraints for thermal-commit plants.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.thermal_commit!-Tuple{JuMP.Model, Dict, Dict}","page":"Thermal Commit","title":"GenX.thermal_commit!","text":"thermal_commit!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the operating constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decision (y in UC).\n\nWe model capacity investment decisions and commitment and cycling (start-up, shut-down) of thermal generators using the integer clustering technique developed in Palmintier, 2011, Palmintier, 2013, and Palmintier, 2014. In a typical binary unit commitment formulation, each unit is either on or off. With the clustered unit commitment formulation, one or more cluster(s) of similar generators are clustered by type and zone (typically using heat rate and fixed O\\&M cost to create clusters), and the integer commitment state variable for each cluster varies from zero to the number of units in the cluster, fracDelta^total_yzOmega^size_yz. As discussed in \\cite{Palmintier2014}, this approach replaces the large set of binary commitment decisions and associated constraints, which scale directly with the number of individual units, with a smaller set of integer commitment states and constraints, one for each cluster y. The dimensionality of the problem thus scales with the number of units of a given type in each zone, rather than by the number of discrete units, significantly improving computational efficiency. However, this method entails the simplifying assumption that all clustered units have identical parameters (e.g., capacity size, ramp rates, heat rate) and that all committed units in a given time step t are operating at the same power output per unit.\n\nPower balance expression\n\nThis function adds the sum of power generation from thermal units subject to unit commitment (Theta_y in UCt in Tz in Z) to the power balance expression.\n\nStartup and shutdown events (thermal plant cycling)\n\nCapacitated limits on unit commitment decision variables\n\nThermal resources subject to unit commitment (y in mathcalUC) adhere to the following constraints on commitment states, startup events, and shutdown events, which limit each decision to be no greater than the maximum number of discrete units installed (as per the following three constraints):\n\nbeginaligned\nnu_yzt leq fracDelta^texttotal_yzOmega^size_yz\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\nchi_yzt leq fracDelta^texttotal_yzOmega^size_yz\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\nzeta_yzt leq fracDelta^texttotal_yzOmega^size_yz\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 1-3 in the code)\n\nwhere decision nu_yzt designates the commitment state of generator cluster y in zone z at time t, decision chi_yzt represents number of startup decisions, decision zeta_yzt represents number of shutdown decisions, Delta^texttotal_yz is the total installed capacity, and parameter Omega^size_yz is the unit size.\n\nCommitment state constraint linking start-up and shut-down decisions\n\nAdditionally, the following constarint maintains the commitment state variable across time, nu_yzt, as the sum of the commitment state in the prior, nu_yzt-1, period plus the number of units started in the current period, chi_yzt, less the number of units shut down in the current period, zeta_yzt:\n\nbeginaligned\nnu_yzt =nu_yzt-1 + chi_yzt - zeta_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT^interior \nnu_yzt =nu_yzt +tau^period-1 + chi_yzt - zeta_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT^start\nendaligned\n\n(See Constraint 4 in the code)\n\nLike other time-coupling constraints, this constraint wraps around to link the commitment state in the first time step of the year (or each representative period), t in mathcalT^start, to the last time step of the year (or each representative period), t+tau^period-1.\n\nRamping constraints\n\nThermal resources subject to unit commitment (y in UC) adhere to the following ramping constraints on hourly changes in power output:\n\nbeginaligned\n\tTheta_yzt-1 + f_y z t-1+r_y z t-1 - Theta_yzt-f_y z tleq kappa^down_yz cdot Omega^size_yz cdot (nu_yzt - chi_yzt) 6pt\n\tqquad - rho^min_yz cdot Omega^size_yz cdot chi_yzt hspace05cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT 6pt\n\tqquad + textmin( rho^max_yzt textmax( rho^min_yz kappa^down_yz ) ) cdot Omega^size_yz cdot zeta_yzt \nendaligned\n\nbeginaligned\n\tTheta_yzt+f_y z t+r_y z t - Theta_yzt-1- f_y z t-1 leq kappa^up_yz cdot Omega^size_yz cdot (nu_yzt - chi_yzt) 6pt\n\tqquad + textmin( rho^max_yzt textmax( rho^min_yz kappa^up_yz ) ) cdot Omega^size_yz cdot chi_yzt hspace05cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT 6pt\n\tqquad - rho^min_yz cdot Omega^size_yz cdot zeta_yzt \nendaligned\n\n(See Constraints 5-6 in the code)\n\nwhere decision Theta_yzt, f_y z t, and r_y z t are respectively, the energy injected into the grid, regulation, and reserve by technology y in zone z at time t, parameter kappa_yzt^updown is the maximum ramp-up or ramp-down rate as a percentage of installed capacity, parameter rho_yz^min is the minimum stable power output per unit of installed capacity, and parameter rho_yzt^max is the maximum available generation per unit of installed capacity. These constraints account for the ramping limits for committed (online) units as well as faster changes in power enabled by units starting or shutting down in the current time step.\n\nMinimum and maximum power output\n\nIf not modeling regulation and spinning reserves, thermal resources subject to unit commitment adhere to the following constraints that ensure power output does not exceed minimum and maximum feasible levels:\n\nbeginaligned\n\tTheta_yzt geq rho^min_yz times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt leq rho^max_yz times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 7-8 the code)\n\nIf modeling reserves and regulation, these constraints are replaced by those established in this thermal_commit_operational_reserves().\n\nMinimum and maximum up and down time\n\nThermal resources subject to unit commitment adhere to the following constraints on the minimum time steps after start-up before a unit can shutdown again (minimum up time) and the minimum time steps after shut-down before a unit can start-up again (minimum down time):\n\nbeginaligned\n\tnu_yzt geq displaystyle sum_hatt = t-(tau^up_yz-1)^t chi_yzhatt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tfracoverlineDelta_yz + Omega_yz - Delta_yzOmega^size_yz - nu_yzt geq displaystyle sum_hatt = t-(tau^down_yz-1)^t zeta_yzhatt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See Constraints 9-10 in the code)\n\nwhere tau_yz^updown is the minimum up or down time for units in generating cluster y in zone z.\n\nLike with the ramping constraints, the minimum up and down constraint time also wrap around from the start of each time period to the end of each period. It is recommended that users of GenX must use longer subperiods than the longest min up/down time if modeling UC. Otherwise, the model will report error.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.thermal_commit_operational_reserves!-Tuple{JuMP.Model, Dict}","page":"Thermal Commit","title":"GenX.thermal_commit_operational_reserves!","text":"thermal_commit_operational_reserves!(EP::Model, inputs::Dict)\n\nThis function is called by the thermal_commit() function when regulation and reserves constraints are active and defines reserve related constraints for thermal power plants subject to unit commitment constraints on power plant start-ups and shut-down decisions.\n\nMaximum contributions to frequency regulation and reserves\n\nWhen modeling frequency regulation and reserves contributions, thermal units subject to unit commitment adhere to the following constraints which limit the maximum contribution to regulation and reserves in each time step to a specified maximum fraction (upsilon^rsv_yz) of the commitment capacity in that time step ((Omega^size_yz cdot nu_yzt)):\n\nbeginaligned\n\tf_yzt leq upsilon^reg_yz times rho^max_yzt (Omega^size_yz times nu_yzt) hspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tr_yzt leq upsilon^rsv_yz times rho^max_yzt (Omega^size_yz times nu_yzt) hspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nwhere f_yzt is the frequency regulation contribution limited by the maximum regulation contribution upsilon^reg_yz, and r_yzt is the reserves contribution limited by the maximum reserves contribution upsilon^rsv_yz. Limits on reserve contributions reflect the maximum ramp rate for the thermal resource in whatever time interval defines the requisite response time for the regulation or reserve products (e.g., 5 mins or 15 mins or 30 mins). These response times differ by system operator and reserve product, and so the user should define these parameters in a self-consistent way for whatever system context they are modeling.\n\nMinimum and maximum power output\n\nWhen modeling frequency regulation and spinning reserves contributions, thermal resources subject to unit commitment adhere to the following constraints that ensure the sum of power output and reserve and/or regulation contributions do not exceed minimum and maximum feasible power output:\n\nbeginaligned\n\tTheta_yzt - f_yzt geq rho^min_yz times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yzt + f_yzt + r_yzt leq rho^max_yzt times Omega^size_yz times nu_yzt\n\thspace15cm forall y in mathcalUC forall z in mathcalZ forall t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/thermal_commit/#GenX.thermal_maintenance_capacity_reserve_margin_adjustment!-Tuple{JuMP.Model, Dict}","page":"Thermal Commit","title":"GenX.thermal_maintenance_capacity_reserve_margin_adjustment!","text":"thermal_maintenance_capacity_reserve_margin_adjustment!(EP::Model, inputs::Dict)\n\nEliminates the contribution of a plant to the capacity reserve margin while it is down for maintenance.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solve_model/#Solving-the-Model","page":"Solving the Model","title":"Solving the Model","text":"","category":"section"},{"location":"Model_Reference/solve_model/","page":"Solving the Model","title":"Solving the Model","text":"Modules = [GenX]\nPages = [\"solve_model.jl\"]","category":"page"},{"location":"Model_Reference/solve_model/#GenX.fix_integers-Tuple{JuMP.Model}","page":"Solving the Model","title":"GenX.fix_integers","text":"fix_integers(jump_model::Model)\n\nThis function fixes the iteger variables ones the model has been solved in order to calculate approximations of dual variables.\n\nArguments\n\njump_model::Model: a model object containing that has been previously solved.\n\nReturns\n\nnothing (modifies an existing-solved model in the memory). solve() must be run again to solve and getdual veriables\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/solve_model/#GenX.solve_model-Tuple{JuMP.Model, Dict}","page":"Solving the Model","title":"GenX.solve_model","text":"solve_model(EP::Model, setup::Dict)\n\nDescription: Solves and extracts solution variables for later processing\n\nArguments\n\nEP::Model: a JuMP model representing the energy optimization problem\nsetup::Dict: a Dict containing GenX setup flags\n\nReturns\n\nEP::Model: the solved JuMP model\nsolver_time::Float64: time taken to solve the model\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/investment_charge/#Investment-Charge","page":"Investment Charge","title":"Investment Charge","text":"","category":"section"},{"location":"Model_Reference/Resources/investment_charge/","page":"Investment Charge","title":"Investment Charge","text":"Modules = [GenX]\nPages = [\"investment_charge.jl\"]","category":"page"},{"location":"Model_Reference/Resources/investment_charge/#GenX.investment_charge!-Tuple{JuMP.Model, Dict, Dict}","page":"Investment Charge","title":"GenX.investment_charge!","text":"investment_charge!(EP::Model, inputs::Dict)\n\nThis function defines the expressions and constraints keeping track of total available storage charge capacity across all resources as well as constraints on capacity retirements. The function also adds investment and fixed O\\&M related costs related to charge capacity to the objective function.\n\nThe total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity.\n\nbeginaligned\n Delta^totalcharge_yz =(overlineDelta^charge_yz+Omega^charge_yz-Delta^charge_yz) forall y in mathcalO^asym z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity.\n\nbeginaligned\nDelta^charge_yz leq overlineDelta^charge_yz\n\thspace4 cm forall y in mathcalO^asym z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^charge and underlineOmega_yz^charge is defined, then we impose constraints on minimum and maximum power capacity.\n\nbeginaligned\n Delta^totalcharge_yz leq overlineOmega^charge_yz\n\thspace4 cm forall y in mathcalO^asym z in mathcalZ \n Delta^totalcharge_yz geq underlineOmega^charge_yz\n\thspace4 cm forall y in mathcalO^asym z in mathcalZ\nendaligned\n\nIn addition, this function adds investment and fixed O&M related costs related to charge capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalO^asym sum_z in mathcalZ\n\tleft( (pi^INVESTcharge_yz times Omega^charge_yz)\n\t+ (pi^FOMcharge_yz times Delta^totalcharge_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#Co-located-VRE-Storage-Module","page":"Co-located VRE and Storage","title":"Co-located VRE-Storage Module","text":"","category":"section"},{"location":"Model_Reference/Resources/vre_stor/","page":"Co-located VRE and Storage","title":"Co-located VRE and Storage","text":"Modules = [GenX]\nPages = [\"vre_stor.jl\"]","category":"page"},{"location":"Model_Reference/Resources/vre_stor/#GenX.inverter_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.inverter_vre_stor!","text":"inverter_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the inverter component of each co-located VRE and storage generator.\n\nThe total inverter capacity of each resource is defined as the sum of the existing inverter capacity plus the newly invested inverter capacity minus any retired inverter capacity:\n\nbeginaligned\n Delta^total inv_yz = (overlineDelta^inv_yz + Omega^inv_yz - Delta^inv_yz) quad forall y in mathcalVS^inv z in mathcalZ\nendaligned\n\nOne cannot retire more inverter capacity than existing inverter capacity:\n\nbeginaligned\n Delta^inv_yz leq overlineDelta^inv_yz\n hspace4 cm forall y in mathcalVS^inv z in mathcalZ\n endaligned\n\nFor resources where overlineOmega^inv_yz and underlineOmega^inv_yz are defined, then we impose constraints on minimum and maximum capacity:\n\nbeginaligned\n Delta^total inv_yz leq overlineOmega^inv_yz\n hspace4 cm forall y in mathcalVS^inv z in mathcalZ \n Delta^total inv_yz geq underlineOmega^inv_yz\n hspace4 cm forall y in mathcalVS^inv z in mathcalZ\nendaligned\n\nThe last constraint ensures that the maximum DC grid exports and imports must be less than the inverter capacity. Without any capacity reserve margin or operating reserves, the constraint is:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt) + fracPi_yzt^dceta^inverter_yz leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nWith only capacity reserve margins, the maximum DC grid exports and imports constraint becomes:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt + Theta^CRMdc_yzt) + fracPi_yzt^dc + Pi_yzt^CRMdceta^inverter_yz \n leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nWith only operating reserves, the maximum DC grid exports and imports constraint becomes:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt + f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) + fracPi_yzt^dc + f^dccha_yzteta^inverter_yz \n leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nWith both capacity reserve margins and operating reserves, the maximum DC grid exports and imports constraint becomes:\n\nbeginaligned\n eta^inverter_yz times (Theta^pv_yzt + Theta^dc_yzt + Theta^CRMdc_yzt + f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) \n + fracPi_yzt^dc + Pi_yzt^CRMdc + f^dccha_yzteta^inverter_yz leq Delta^total inv_yz quad forall y in mathcalVS^inv forall z in mathcalZ forall t in mathcalT\nendaligned\n\nIn addition, this function adds investment and fixed O&M related costs related to the inverter capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^inv sum_z in mathcalZ\n left( (pi^INVEST inv_yz times Omega^inv_yz)\n + (pi^FOM inv_yz times Delta^totalinv_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.investment_charge_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.investment_charge_vre_stor!","text":"investment_charge_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function activates the decision variables and constraints for asymmetric storage resources (independent charge and discharge power capacities (any STOR flag = 2)). For asymmetric storage resources, the function is enabled so charging and discharging can occur either through DC or AC capabilities. For example, a storage resource can be asymmetrically charged and discharged via DC capabilities or a storage resource could be charged via AC capabilities and discharged through DC capabilities. This module is configured such that both AC and DC charging (or discharging) cannot simultaneously occur.\n\nThe total charge/discharge DC and AC capacities of each resource are defined as the sum of the existing charge/discharge DC and AC capacities plus the newly invested charge/discharge DC and AC capacities minus any retired charge/discharge DC and AC capacities:\n\nbeginaligned\n Delta^totaldcdis_yz =(overlineDelta^dcdis_yz+Omega^dcdis_yz-Delta^dcdis_yz) quad forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^totaldccha_yz =(overlineDelta^dccha_yz+Omega^dccha_yz-Delta^dccha_yz) quad forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^totalacdis_yz =(overlineDelta^acdis_yz+Omega^acdis_yz-Delta^acdis_yz) quad forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^totalaccha_yz =(overlineDelta^accha_yz+Omega^accha_yz-Delta^accha_yz) quad forall y in mathcalVS^asymaccha z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity:\n\nbeginaligned\n Delta^dcdis_yz leq overlineDelta^dcdis_yz\n hspace4 cm forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^dccha_yz leq overlineDelta^dccha_yz\n hspace4 cm forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^acdis_yz leq overlineDelta^acdis_yz\n hspace4 cm forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^accha_yz leq overlineDelta^accha_yz\n hspace4 cm forall y in mathcalVS^asymaccha z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^dcdis overlineOmega_yz^dccha overlineOmega_yz^acdis overlineOmega_yz^accha and underlineOmega_yz^dcdis underlineOmega_yz^dccha underlineOmega_yz^acdis underlineOmega_yz^ac cha are defined, then we impose constraints on minimum and maximum charge/discharge DC and AC power capacity:\n\nbeginaligned\n Delta^totaldcdis_yz leq overlineOmega^dcdis_yz\n hspace4 cm forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^totaldcdis_yz geq underlineOmega^dcdis_yz\n hspace4 cm forall y in mathcalVS^asymdcdis z in mathcalZ \n Delta^totaldccha_yz leq overlineOmega^dccha_yz\n hspace4 cm forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^totaldccha_yz geq underlineOmega^dccha_yz\n hspace4 cm forall y in mathcalVS^asymdccha z in mathcalZ \n Delta^totalacdis_yz leq overlineOmega^acdis_yz\n hspace4 cm forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^totalacdis_yz geq underlineOmega^acdis_yz\n hspace4 cm forall y in mathcalVS^asymacdis z in mathcalZ \n Delta^totalaccha_yz leq overlineOmega^accha_yz\n hspace4 cm forall y in mathcalVS^asymaccha z in mathcalZ \n Delta^totalaccha_yz geq underlineOmega^accha_yz\n hspace4 cm forall y in mathcalVS^asymaccha z in mathcalZ \nendaligned\n\nFurthermore, for storage technologies with asymmetric charge and discharge capacities (all y in mathcalVS^asymdcdis y in mathcalVS^asymdccha y in mathcalVS^asymacdis y in mathcalVS^asymaccha), the charge rate, Pi^dc_yzt Pi^ac_yzt, is constrained by the total installed charge capacity, Delta^totaldccha_yz Delta^totalaccha_yz. Similarly the discharge rate, Theta^dc_yzt Theta^ac_yzt, is constrained by the total installed discharge capacity, Delta^totaldcdis_yz Delta^totalacdis_yz. Without any activated capacity reserve margin policies or operating reserves, the constraints are as follows:\n\nbeginaligned\n Theta^dc_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nAdding only the capacity reserve margin constraints, the asymmetric charge and discharge DC and AC rates plus the 'virtual' charge and discharge DC and AC rates are constrained by the total installed charge and discharge DC and AC capacities:\n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt + Pi^CRMdc_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt + Pi^CRMac_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nAdding only the operating reserve constraints, the asymmetric charge and discharge DC and AC rates plus the contributions to frequency regulation and operating reserves (both DC and AC) are constrained by the total installed charge and discharge DC and AC capacities:\n\nbeginaligned\n Theta^dc_yzt + f^dcdis_yzt + r^dcdis_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt + f^dccha_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt + f^acdis_yzt + r^acdis_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt + f^accha_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nWith both capacity reserve margin and operating reserve constraints, the asymmetric charge and discharge DC and AC rate constraints follow: \n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt + f^dcdis_yzt + r^dcdis_yzt leq Delta^totaldcdis_yz quad forall y in mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n\t Pi^dc_yzt + Pi^CRMdc_yzt + f^dccha_yzt leq Delta^totaldccha_yz quad forall y in mathcalVS^asymdccha z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt + f^acdis_yzt + r^acdis_yzt leq Delta^totalacdis_yz quad forall y in mathcalVS^asymacdis z in mathcalZ t in mathcalT \n\t Pi^ac_yzt + Pi^CRMac_yzt + f^accha_yzt leq Delta^totalaccha_yz quad forall y in mathcalVS^asymaccha z in mathcalZ t in mathcalT \nendaligned\n\nIn addition, this function adds investment and fixed O&M costs related to charge/discharge AC and DC capacities to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^asymdcdis sum_z in mathcalZ\n left( (pi^INVESTdcdis_yz times Omega^dcdis_yz)\n + (pi^FOMdcdis_yz times Delta^totaldcdis_yz)right) \n \t+ sum_y in mathcalVS^asymdccha sum_z in mathcalZ\n left( (pi^INVESTdccha_yz times Omega^dccha_yz)\n + (pi^FOMdccha_yz times Delta^totaldccha_yz)right) \n \t+ sum_y in mathcalVS^asymacdis sum_z in mathcalZ\n left( (pi^INVESTacdis_yz times Omega^acdis_yz)\n + (pi^FOMacdis_yz times Delta^totalacdis_yz)right) \n \t+ sum_y in mathcalVS^asymaccha sum_z in mathcalZ\n left( (pi^INVESTaccha_yz times Omega^accha_yz)\n + (pi^FOMaccha_yz times Delta^totalaccha_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.lds_vre_stor!-Tuple{JuMP.Model, Dict}","page":"Co-located VRE and Storage","title":"GenX.lds_vre_stor!","text":"lds_vre_stor!(EP::Model, inputs::Dict)\n\nThis function defines the decision variables, expressions, and constraints for any long duration energy storage component of each co-located VRE and storage generator ( there is more than one representative period and LDS_VRE_STOR=1 in the Vre_and_stor_data.csv). \n\nThese constraints follow the same formulation that is outlined by the function long_duration_storage!() in the storage module. One constraint changes, which links the state of charge between the start of periods for long duration energy storage resources because there are options to charge and discharge these resources through AC and DC capabilities. The main linking constraint changes to:\n\nbeginaligned\n Gamma_yz(m-1)times tau^period+1 =left(1-eta_yz^lossright) times left(Gamma_yzmtimes tau^period -Delta Q_yzmright) \n - fracTheta^dc_yz(m-1) times tau^period+1eta_yz^dischargedc - fracTheta^ac_yz(m-1)times tau^period+1eta_yz^dischargeac \n + eta_yz^chargedc times Pi^dc_yz(m-1)times tau^period+1 + eta_yz^chargeac times Pi^ac_yz(m-1)times tau^period+1 quad forall y in mathcalVS^LDES z in mathcalZ m in mathcalM\nendaligned\n\nThe rest of the long duration energy storage constraints are copied and applied to the co-located VRE and storage module for any long duration energy storage resources y in mathcalVS^LDES from the long-duration storage module. Capacity reserve margin constraints for long duration energy storage resources are further elaborated upon in vre_stor_capres!().\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.solar_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.solar_vre_stor!","text":"solar_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the solar PV component of each co-located VRE and storage generator.\n\nThe total solar PV capacity of each resource is defined as the sum of the existing solar PV capacity plus the newly invested solar PV capacity minus any retired solar PV capacity:\n\nbeginaligned\n Delta^total pv_yz = (overlineDelta^pv_yz + Omega^pv_yz - Delta^pv_yz) quad forall y in mathcalVS^pv z in mathcalZ\nendaligned\n\nOne cannot retire more solar PV capacity than existing solar PV capacity:\n\nbeginaligned\n Delta^pv_yz leq overlineDelta^pv_yz\n hspace4 cm forall y in mathcalVS^pv z in mathcalZ\nendaligned\n\nFor resources where overlineOmega^pv_yz and underlineOmega^pv_yz are defined, then we impose constraints on minimum and maximum capacity:\n\nbeginaligned\n Delta^total pv_yz leq overlineOmega^pv_yz\n hspace4 cm forall y in mathcalVS^pv z in mathcalZ \n Delta^total pv_yz geq underlineOmega^pv_yz\n hspace4 cm forall y in mathcalVS^pv z in mathcalZ\nendaligned\n\nIf there is a fixed ratio for capacity (rather than co-optimizing interconnection sizing) of solar PV built to capacity of inverter built (eta_yz^ILRpv), also known as the inverter loading ratio, then we impose the following constraint:\n\nbeginaligned\n Delta^total pv_y z = eta^ILRpv_y z times Delta^total inv_y z quad forall y in mathcalVS^pv forall z in Z\nendaligned\n\nThe last constraint defines the maximum power output in each time step from the solar PV component. Without any operating reserves, the constraint is:\n\nbeginaligned\n Theta^pv_y z t leq rho^max pv_y z t times Delta^totalpv_y z quad forall y in mathcalVS^pv forall z in Z forall t in T\nendaligned\n\nWith operating reserves, the maximum power output in each time step from the solar PV component must account for procuring some of the available capacity for frequency regulation (f^pv_yzt) and upward operating (spinning) reserves (r^pv_yzt):\n\nbeginaligned\n Theta^pv_y z t + f^pv_yzt + r^pv_yzt leq rho^max pv_y z t times Delta^totalpv_y z quad forall y in mathcalVS^pv forall z in Z forall t in T\nendaligned\n\nIn addition, this function adds investment, fixed O&M, and variable O&M costs related to the solar PV capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^pv sum_z in mathcalZ\n left( (pi^INVEST pv_yz times Omega^pv_yz) + (pi^FOM pv_yz times Delta^totalpv_yz) right) \n + sum_y in mathcalVS^pv sum_z in mathcalZ sum_t in mathcalT (pi^VOM pv_yz times eta^inverter_yz times Theta^pv_yzt)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.stor_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.stor_vre_stor!","text":"stor_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the storage component of each co-located VRE and storage generator. A wide range of energy storage devices (all y in mathcalVS^stor) can be modeled in GenX, using one of two generic storage formulations: (1) storage technologies with symmetric charge and discharge capacity (all y in mathcalVS^symdc cup y in mathcalVS^symac), such as lithium-ion batteries and most other electrochemical storage devices that use the same components for both charge and discharge; and (2) storage technologies that employ distinct and potentially asymmetric charge and discharge capacities (all y in mathcalVS^asymdcdis cup y in mathcalVS^asymdccha cup y in mathcalVS^asymacdis cup y in mathcalVS^asymaccha), such as most thermal storage technologies or hydrogen electrolysis/storage/fuel cell or combustion turbine systems. The following constraints apply to all storage resources, y in mathcalVS^stor, regardless of whether or not the storage has symmetric or asymmetric charging/discharging capabilities or varying durations of discharge. \n\nThe total storage energy capacity of each resource is defined as the sum of the existing storage energy capacity plus the newly invested storage energy capacity minus any retired storage energy capacity:\n\nbeginaligned\n Delta^totalenergy_yz = (overlineDelta^energy_yz+Omega^energy_yz-Delta^energy_yz) quad forall y in mathcalVS^stor z in mathcalZ\nendaligned\n\nOne cannot retire more energy capacity than existing energy capacity:\n\nbeginaligned\n Delta^energy_yz leq overlineDelta^energy_yz\n hspace4 cm forall y in mathcalVS^stor z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz^energy and underlineOmega_yz^energy are defined, then we impose constraints on minimum and maximum energy capacity:\n\nbeginaligned\n Delta^totalenergy_yz leq overlineOmega^energy_yz\n hspace4 cm forall y in mathcalVS^stor z in mathcalZ \n Delta^totalenergy_yz geq underlineOmega^energy_yz\n hspace4 cm forall y in mathcalVS^stor z in mathcalZ\nendaligned\n\nThe following two constraints track the state of charge of the storage resources at the end of each time period, relating the volume of energy stored at the end of the time period, Gamma_yzt, to the state of charge at the end of the prior time period, Gamma_yzt-1, the DC and AC charge and discharge decisions in the current time period, Pi^dc_yzt Pi^ac_yzt Theta^dc_yzt Theta^ac_yzt, and the self discharge rate for the storage resource (if any), eta_yz^loss. When modeling the entire year as a single chronological period with total number of time steps of tau^period, storage inventory in the first time step is linked to storage inventory at the last time step of the period representing the year. Alternatively, when modeling the entire year with multiple representative periods, this constraint relates storage inventory in the first timestep of the representative period with the inventory at the last time step of the representative period, where each representative period is made of tau^period time steps. In this implementation, energy exchange between representative periods is not permitted. When modeling representative time periods, GenX enables modeling of long duration energy storage which tracks state of charge between representative periods enable energy to be moved throughout the year. If there is more than one representative period and LDS_VRE_STOR=1 has been enabled for resources in Vre_and_stor_data.csv, this function calls lds_vre_stor!() to enable this feature. The first of these two constraints enforces storage inventory balance for interior time steps (t in mathcalT^interior), while the second enforces storage balance constraint for the initial time step (t in mathcalT^start):\n\nbeginaligned\n\t Gamma_yzt = Gamma_yzt-1 - fracTheta^dc_yzteta_yz^dischargedc - fracTheta^ac_yzteta_yz^dischargeac + eta_yz^chargedc times Pi^dc_yzt + eta_yz^chargeac times Pi^ac_yzt \n - eta_yz^loss times Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^interior\n\t Gamma_yzt = Gamma_yzt+tau^period-1 - fracTheta^dc_yzteta_yz^dischargedc - fracTheta^ac_yzteta_yz^dischargeac + eta_yz^chargedc times Pi^dc_yzt + eta_yz^chargeac times Pi^ac_yzt \n - eta_yz^loss times Gamma_yzt+tau^period-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^start\nendaligned\n\nThe last constraint limits the volume of energy stored at any time, Gamma_yzt, to be less than the installed energy storage capacity, Delta^total energy_yz. \n\nbeginaligned\n\t Gamma_yzt leq Delta^total energy_yz quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nThe next set of constraints only apply to symmetric storage resources (all y in mathcalVS^symdc cup y in mathcalVS^symac). For storage technologies with symmetric charge and discharge capacity (all y in mathcalVS^symdc cup y in mathcalVS^symac), since storage resources generally represent a 'cluster' of multiple similar storage devices of the same type/cost in the same zone, GenX permits storage resources to simultaneously charge and discharge (as some units could be charging while others discharge). The simultaneous sum of DC and AC charge, Pi^dc_yzt Pi^ac_yzt, and discharge, Theta^dc_yzt Theta^ac_yzt, is limited by the total installed energy capacity, Delta^total energy_oz, multiplied by the power to energy ratio, mu_yz^dcstor mu_yz^acstor. Without any capacity reserve margin constraints or operating reserves, the symmetric AC and DC storage resources are constrained as:\n\nbeginaligned\n\t Theta^dc_yzt + Pi^dc_yzt leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + Pi^ac_yzt leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nSymmetric storage resources with only capacity reserve margin constraints follow a similar constraint that incorporates the 'virtual' discharging and charging that occurs and limits the simultaneously charging, discharging, virtual charging, and virtual discharging of the battery resource: \n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt + Pi^dc_yzt + Pi^CRMdc_yzt \n leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt + Pi^ac_yzt + Pi^CRMac_yzt \n leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nSymmetric storage resources only subject to operating reserves have additional variables to represent contributions of frequency regulation and upwards operating reserves while the storage is charging DC or AC (f^dccha_yzt f^accha_yzt) and discharging DC or AC (f^dcdis_yzt f^acdis_yzt r^dcdis_yzt r^acdis_yzt). Note that as storage resources can contribute to regulation and reserves while either charging or discharging, the proxy variables f^dccha_yzt f^accha_yzt f^dcdis_yzt f^acdis_yzt r^dcdis_yzt r^acdis_yzt are created for storage components.\n\nbeginaligned\n Theta^dc_yzt + f^dcdis_yzt + r^dcdis_yzt + Pi^dc_yzt + f^dccha_yzt \n leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + f^acdis_yzt + r^acdis_yzt + Pi^ac_yzt + f^accha_yzt \n leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nFor symmetric storage resources with both capacity reserve margin and operating reserves, DC and AC resources are subject to the following constraints:\n\nbeginaligned\n Theta^dc_yzt + Theta^CRMdc_yzt + f^dcdis_yzt + r^dcdis_yzt + Pi^dc_yzt + Pi^CRMdc_yzt + f^dccha_yzt \n leq mu^dcstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symdc z in mathcalZ t in mathcalT \n Theta^ac_yzt + Theta^CRMac_yzt + f^acdis_yzt + r^acdis_yzt + Pi^ac_yzt + Pi^CRMac_yzt + f^accha_yzt \n leq mu^acstor_yz times Delta^totalenergy_yz quad forall y in mathcalVS^symac z in mathcalZ t in mathcalT\nendaligned\n\nLong duration energy storage constraints are activated by the function lds_vre_stor!(). Asymmetric storage resource constraints are activated by the function investment_charge_vre_stor!().\n\nIn addition, this function adds investment, fixed O&M, and variable O&M costs related to the storage capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^stor sum_z in mathcalZ\n left( (pi^INVEST energy_yz times Omega^energy_yz) + (pi^FOM energy_yz times Delta^totalenergy_yz) right) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis sum_z in mathcalZ sum_t in mathcalT (pi^VOMdcdis_yz times eta^inverter_yz times Theta^dc_yzt) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdccha sum_z in mathcalZ sum_t in mathcalT (pi^VOMdccha_yz times fracPi^dc_yzteta^inverter_yz) \n + sum_y in mathcalVS^symac cup mathcalVS^asymacdis sum_z in mathcalZ sum_t in mathcalT (pi^VOMacdis_yz times Theta^ac_yzt) \n + sum_y in mathcalVS^symac cup mathcalVS^asymaccha sum_z in mathcalZ sum_t in mathcalT (pi^VOMaccha_yz times Pi^ac_yzt)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.vre_stor!","text":"vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis module enables the modeling of 1) co-located VRE and energy storage technologies, and 2) optimized interconnection sizing for VREs. Utility-scale solar PV and/or wind VRE technologies can be modeled at the same site with or without storage technologies. Storage resources can be charged/discharged behind the meter through the inverter (DC) and through AC charging/discharging capabilities. Each resource can be configured to have any combination of the following components: solar PV, wind, DC discharging/charging storage, and AC discharging/charging storage resources. For storage resources, both long duration energy storage and short-duration energy storage can be modeled, via asymmetric or symmetric charging and discharging options. Each resource connects to the grid via a grid connection component, which is the only required decision variable that each resource must have. If the configured resource has either solar PV and/or DC discharging/charging storage capabilities, an inverter decision variable is also created. The full module with the decision variables and interactions can be found below. \n\n(Image: Configurable Co-located VRE and Storage Module Interactions and Decision Variables) Figure. Configurable Co-located VRE and Storage Module Interactions and Decision Variables\n\nThis module is split such that functions are called for each configurable component of a co-located resource: inverter_vre_stor(), solar_vre_stor!(), wind_vre_stor!(), stor_vre_stor!(), lds_vre_stor!(), and investment_charge_vre_stor!(). The function vre_stor!() specifically ensures that all necessary functions are called to activate the appropriate constraints, creates constraints that apply to multiple components (i.e. inverter and grid connection balances and maximums), and activates all of the policies that have been created (minimum capacity requirements, maximum capacity requirements, capacity reserve margins, operating reserves, and energy share requirements can all be turned on for this module). Note that not all of these variables are indexed by each co-located VRE and storage resource (for example, some co-located resources may only have a solar PV component and battery technology or just a wind component). Thus, the function vre_stor!() ensures indexing issues do not arise across the various potential configurations of co-located VRE and storage module but showcases all constraints as if each decision variable (that may be only applicable to certain components) is indexed by each y in mathcalVS for readability. \n\nThe first constraint is created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains and regardless of the policies invoked for the module. This constraint represents the energy balance, ensuring net DC power (discharge of battery, PV generation, and charge of battery) and net AC power (discharge of battery, wind generation, and charge of battery) are equal to the technology's total discharging to and charging from the grid:\n\nbeginaligned\n Theta_yzt - Pi_yzt = Theta_yzt^wind + Theta_yzt^ac - Pi_yzt^ac + eta^inverter_yz times (Theta_yzt^pv + Theta_yzt^dc) - fracPi^dc_yzteta^inverter_yz \n forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint is also created with the function vre_stor!() and exists for all resources, regardless of the VRE and storage components that each resource contains. However, this constraint changes when either or both capacity reserve margins and operating reserves are activated. The following constraint enforces that the maximum grid exports and imports must be less than the grid connection capacity (without any policies):\n\nbeginaligned\n Theta_yzt + Pi_yzt leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint with only capacity reserve margins activated is:\n\nbeginaligned\n Theta_yzt + Pi_yzt + Theta^CRMac_yzt + Pi^CRMac_yzt + eta^inverter_yz times Theta^CRMdc_yzt + fracPi^CRMdc_yzteta^inverter_yz \n leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint with only operating reserves activated is:\n\nbeginaligned\n Theta_yzt + Pi_yzt + f^acdis_yzt + r^acdis_yzt + f^accha_yzt + f^wind_yzt + r^wind_yzt \n + eta^inverter_yz times (f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) + fracf^dccha_yzteta^inverter_yz leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe second constraint with both capacity reserve margins and operating reserves activated is:\n\nbeginaligned\n Theta_yzt + Pi_yzt + Theta^CRMac_yzt + Pi^CRMac_yzt + f^acdis_yzt + r^acdis_yzt + f^accha_yzt + f^wind_yzt + r^wind_yzt \n + eta^inverter_yz times (Theta^CRMdc_yzt + f^pv_yzt + r^pv_yzt + f^dcdis_yzt + r^dcdis_yzt) + fracPi^CRMdc_yzt + f^dccha_yzteta^inverter_yz \n leq Delta^total_yz quad forall y in mathcalVS forall z in mathcalZ forall t in mathcalT\nendaligned\n\nThe rest of the constraints are dependent upon specific configurable components within the module and are listed below.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.vre_stor_capres!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.vre_stor_capres!","text":"vre_stor_capres!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function activates capacity reserve margin constraints for co-located VRE and storage resources. The capacity reserve margin formulation for GenX is further elaborated upon in cap_reserve_margin!(). For co-located resources (y in mathcalVS), the available capacity to contribute to the capacity reserve margin is the net injection into the transmission network (which can come from the solar PV, wind, and/or storage component) plus the net virtual injection corresponding to charge held in reserve (which can only come from the storage component), derated by the derating factor. If a capacity reserve margin is modeled, variables for virtual charge DC, Pi^CRM dc_yzt, virtual charge AC, Pi^CRM ac_yzt, virtual discharge DC, Theta^CRM dc_yzt, virtual discharge AC, Theta^CRM ac_ozt, and virtual state of charge, Gamma^CRM_yzt, are created to represent contributions that a storage device makes to the capacity reserve margin without actually generating power. These represent power that the storage device could have discharged or consumed if called upon to do so, based on its available state of charge. Importantly, a dedicated set of variables and constraints are created to ensure that any virtual contributions to the capacity reserve margin could be made as actual charge/discharge if necessary without affecting system operations in any other timesteps (similar to the standalone storage capacity reserve margin constraints). \n\nIf a capacity reserve margin is modeled, then the following constraints track the relationship between the virtual charge variables, Pi^CRMdc_yzt Pi^CRMac_yzt, virtual discharge variables, Theta^CRM dc_yzt Theta^CRM ac_yzt, and the virtual state of charge, Gamma^CRM_yzt, representing the amount of state of charge that must be held in reserve to enable these virtual capacity reserve margin contributions and ensuring that the storage device could deliver its pledged capacity if called upon to do so without affecting its operations in other timesteps. Gamma^CRM_yzt is tracked similarly to the devices' overall state of charge based on its value in the previous timestep and the virtual charge and discharge in the current timestep. Unlike the regular state of charge, virtual discharge Theta^CRMdc_yzt Theta^CRMac_yzt increases Gamma^CRM_yzt (as more charge must be held in reserve to support more virtual discharge), and the virtual charge Pi^CRMdc_yzt Pi^CRMac_yzt reduces Gamma^CRM_yzt. Similar to the state of charge constraints in the stor_vre_stor!() function, the first of these two constraints enforces storage inventory balance for interior time steps (t in mathcalT^interior), while the second enforces storage balance constraint for the initial time step (t in mathcalT^start):\n\nbeginaligned\n\t Gamma^CRM_yzt = Gamma^CRM_yzt-1 + fracTheta^CRM dc_yzteta_yz^dischargedc + fracTheta^CRMac_yzteta_yz^dischargeac - eta_yz^chargedc times Pi^CRMdc_yzt - eta_yz^chargeac times Pi^CRM ac_yzt \n - eta_yz^loss times Gamma^CRM_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^interior\n Gamma^CRM_yzt = Gamma^CRM_yzt+tau^period-1 + fracTheta^CRMdc_yzteta_yz^dischargedc + fracTheta^CRMac_yzteta_yz^dischargeac - eta_yz^chargedc times Pi^CRMdc_yzt - eta_yz^chargeac times Pi^CRMac_yzt \n - eta_yz^loss times Gamma^CRM_yzt+tau^period-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT^start\nendaligned\n\nThe energy held in reserve, Gamma^CRM_yzt, also acts as a lower bound on the overall state of charge Gamma_yzt. This ensures that the storage device cannot use state of charge that would not have been available had it been called on to actually contribute its pledged virtual discharge at some earlier timestep. This relationship is described by the following constraint (as also outlined in the storage module):\n\nbeginaligned\n\t Gamma_yzt geq Gamma^CRM_yzt quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT \nendaligned\n\nThe overall contribution of the co-located VRE and storage resources to the system's capacity reserve margin in timestep t is equal to (including both actual and virtual DC and AC charge and discharge):\n\nbeginaligned\n\t sum_y in mathcalVS^pv (epsilon_yzp^CRM times eta^inverter_yz times rho^maxpv_yzt times Delta^totalpv_yz) \n + sum_y in mathcalVS^wind (epsilon_yzp^CRM times rho^maxwind_yzt times Delta^totalwind_yz) \n + sum_y in mathcalVS^symdc cup mathcalVS^asymdcdis (epsilon_yzp^CRM times eta^inverter_yz times (Theta^dc_yzt + Theta^CRMdc_yzt)) \n + sum_y in mathcalVS^symac cup mathcalVS^asymacdis (epsilon_yzp^CRM times (Theta^ac_yzt + Theta^CRMac_yzt)) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times fracPi^dc_yzt + Pi^CRMdc_yzteta^inverter_yz) \n - sum_y in mathcalVS^symdc cup mathcalVS^asymdccha (epsilon_yzp^CRM times (Pi^ac_yzt + Pi^CRMac_yzt))\nendaligned\n\nIf long duration energy storage resources exist, a separate but similar set of variables and constraints is used to track the evolution of energy held in reserves across representative periods, which is elaborated upon in the long_duration_storage!() function. The main linking constraint follows (due to the capabilities of virtual DC and AC discharging and charging):\n\nbeginaligned\n Gamma^CRM_yz(m-1)times tau^period+1 = left(1-eta_yz^lossright)times left(Gamma^CRM_yzmtimes tau^period -Delta Q_yzmright) \n + fracTheta^CRMdc_yz(m-1)times tau^period+1eta_yz^dischargedc + fracTheta^CRMac_yz(m-1)times tau^period+1eta_yz^dischargeac \n - eta_yz^chargedc times Pi^CRMdc_yz(m-1)times tau^period+1 - eta_yz^chargeac times Pi^CRMac_yz(m-1)times tau^period+1 \n forall y in mathcalVS^LDES z in mathcalZ m in mathcalM\nendaligned\n\nAll other constraints are identical to those used to track the actual state of charge, except with the new variables for the representation of 'virtual' state of charge, build up storage inventory and state of charge at the beginning of each period. \n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.vre_stor_operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.vre_stor_operational_reserves!","text":"vre_stor_operational_reserves!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function activates either or both frequency regulation and operating reserve options for co-located VRE-storage resources. Co-located VRE and storage resources (y in mathcalVS) have six pairs of auxilary variables to reflect contributions to regulation and reserves when generating electricity from solar PV or wind resources, DC charging and discharging from storage resources, and AC charging and discharging from storage resources. The primary variables (f_yzt & r_yzt) becomes equal to the sum of these auxilary variables as follows:\n\nbeginaligned\n f_yzt = f^pv_yzt + f^wind_yzt + f^dcdis_yzt + f^dccha_yzt + f^acdis_yzt + f^accha_yzt quad forall y in mathcalVS z in mathcalZ t in mathcalT\n r_yzt = r^pv_yzt + r^wind_yzt + r^dcdis_yzt + r^dccha_yzt + r^acdis_yzt + r^accha_yzt quad forall y in mathcalVS z in mathcalZ t in mathcalT\nendaligned\n\nFurthermore, the frequency regulation and operating reserves require the maximum contribution from the entire resource to be a specified fraction of the installed grid connection capacity:\n\nbeginaligned\n f_yzt leq upsilon^reg_yz times Delta^total_yz\n hspace4 cm forall y in mathcalVS z in mathcalZ t in mathcalT \n r_yzt leq upsilon^rsv_yztimes Delta^total_yz\n hspace4 cm forall y in mathcalVS z in mathcalZ t in mathcalT\n endaligned\n\nThe following constraints follow if the configurable co-located resource has any type of storage component. When charging, reducing the DC and AC charge rate is contributing to upwards reserve and frequency regulation as it drops net demand. As such, the sum of the DC and AC charge rate plus contribution to regulation and reserves up must be greater than zero. Additionally, the DC and AC discharge rate plus the contribution to regulation must be greater than zero:\n\nbeginaligned\n Pi^dc_yzt - f^dccha_yzt - r^dccha_yzt geq 0 quad forall y in mathcalVS^symdc cup mathcalVS^asymdccha z in mathcalZ t in mathcalT\n Pi^ac_yzt - f^accha_yzt - r^accha_yzt geq 0 quad forall y in mathcalVS^symac cup mathcalVS^asymaccha z in mathcalZ t in mathcalT\n Theta^dc_yzt - f^dcdis_yzt geq 0 quad forall y in mathcalVS^symdc cup mathcalVS^asymdcdis z in mathcalZ t in mathcalT \n Theta^ac_yzt - f^acdis_yzt geq 0 quad forall y in mathcalVS^symac cup mathcalVS^asymacdis z in mathcalZ t in mathcalT\nendaligned\n\nAdditionally, when reserves are modeled, the maximum DC and AC charge rate and contribution to regulation while charging can be no greater than the available energy storage capacity, or the difference between the total energy storage capacity, Delta^total energy_yz, and the state of charge at the end of the previous time period, Gamma_yzt-1, while accounting for charging losses eta_yz^chargedc eta_yz^chargeac. Note that for storage to contribute to reserves down while charging, the storage device must be capable of increasing the charge rate (which increases net load):\n\nbeginaligned\n eta_yz^chargedc times (Pi^dc_yzt + f^dccha_ozt) + eta_yz^chargeac times (Pi^ac_yzt + f^accha_ozt) \n leq Delta^energy total_yz - Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nFinally, the maximum DC and AC discharge rate and contributions to the frequency regulation and operating reserves must be less than the state of charge in the previous time period, Gamma_yzt-1. Without any capacity reserve margin policies activated, the constraint is as follows:\n\nbeginaligned\n fracTheta^dc_yzt+f^dcdis_yzt+r^dcdis_yzteta_yz^dischargedc + fracTheta^ac_yzt+f^acdis_yzt+r^acdis_yzteta_yz^dischargeac \n leq Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nWith the capacity reserve margin policies, the maximum DC and AC discharge rate accounts for both contributions to the capacity reserve margin and operating reserves as follows:\n\nbeginaligned\n fracTheta^dc_yzt+Theta^CRMdc_yzt+f^dcdis_yzt+r^dcdis_yzteta_yz^dischargedc + fracTheta^ac_yzt+Theta^CRMac_yzt+f^acdis_yzt+r^acdis_yzteta_yz^dischargeac \n leq Gamma_yzt-1 quad forall y in mathcalVS^stor z in mathcalZ t in mathcalT\nendaligned\n\nLastly, if the co-located resource has a variable renewable energy component, the solar PV and wind resource can also contribute to frequency regulation reserves and must be greater than zero:\n\nbeginaligned\n Theta^pv_yzt - f^pv_yzt geq 0 quad forall y in mathcalVS^pv z in mathcalZ t in mathcalT \n Theta^wind_yzt - f^wind_yzt geq 0 quad forall y in mathcalVS^wind z in mathcalZ t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.wind_vre_stor!-Tuple{JuMP.Model, Dict, Dict}","page":"Co-located VRE and Storage","title":"GenX.wind_vre_stor!","text":"wind_vre_stor!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the decision variables, expressions, and constraints for the wind component of each co-located VRE and storage generator.\n\nThe total wind capacity of each resource is defined as the sum of the existing wind capacity plus the newly invested wind capacity minus any retired wind capacity:\n\nbeginaligned\n Delta^total wind_yz = (overlineDelta^wind_yz + Omega^wind_yz - Delta^wind_yz) quad forall y in mathcalVS^wind z in mathcalZ\nendaligned\n\nOne cannot retire more wind capacity than existing wind capacity:\n\nbeginaligned\n Delta^wind_yz leq overlineDelta^wind_yz\n hspace4 cm forall y in mathcalVS^wind z in mathcalZ\nendaligned\n\nFor resources where overlineOmega^wind_yz and underlineOmega^wind_yz are defined, then we impose constraints on minimum and maximum capacity:\n\nbeginaligned\n Delta^total wind_yz leq overlineOmega^wind_yz\n hspace4 cm forall y in mathcalVS^wind z in mathcalZ \n Delta^total wind_yz geq underlineOmega^wind_yz\n hspace4 cm forall y in mathcalVS^wind z in mathcalZ\nendaligned\n\nIf there is a fixed ratio for capacity (rather than co-optimizing interconnection sizing) of wind built to capacity of grid connection built (eta_yz^ILRwind), then we impose the following constraint:\n\nbeginaligned\n Delta^total wind_y z = eta^ILRwind_y z times Delta^total_y z quad forall y in mathcalVS^wind forall z in Z\nendaligned\n\nThe last constraint defines the maximum power output in each time step from the wind component. Without any operating reserves, the constraint is:\n\nbeginaligned\n Theta^wind_y z t leq rho^max wind_y z t times Delta^totalwind_y z quad forall y in mathcalVS^wind forall z in Z forall t in T\nendaligned\n\nWith operating reserves, the maximum power output in each time step from the wind component must account for procuring some of the available capacity for frequency regulation (f^wind_yzt) and upward operating (spinning) reserves (r^wind_yzt):\n\nbeginaligned\n Theta^wind_y z t + f^wind_yzt + r^wind_yzt leq rho^max wind_y z t times Delta^totalwind_y z quad forall y in mathcalVS^wind forall z in Z forall t in T\nendaligned\n\nIn addition, this function adds investment, fixed O&M, and variable O&M costs related to the wind capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalVS^wind sum_z in mathcalZ\n left( (pi^INVEST wind_yz times Omega^wind_yz) + (pi^FOM wind_yz times Delta^totalwind_yz) right) \n + sum_y in mathcalVS^wind sum_z in mathcalZ sum_t in mathcalT (pi^VOM wind_yz times Theta^wind_yzt)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor","text":"write_vre_stor(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage specific files.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor_capacity-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor_capacity","text":"write_vre_stor_capacity(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage capacities.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor_charge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor_charge","text":"write_vre_stor_charge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage charging decision variables/expressions.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/vre_stor/#GenX.write_vre_stor_discharge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Co-located VRE and Storage","title":"GenX.write_vre_stor_discharge","text":"write_vre_stor_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the vre-storage discharging decision variables/expressions.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Reading-Input-Files","page":"Inputs Functions","title":"Reading Input Files","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_inputs.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.get_systemfiles_path-Tuple{Dict, AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.get_systemfiles_path","text":"get_systemfiles_path(setup::Dict, TDR_directory::AbstractString, path::AbstractString)\n\nDetermine the directory based on the setup parameters.\n\nThis function checks if the TimeDomainReduction setup parameter is equal to 1 and if time domain reduced files exist in the data directory. If the condition is met, it returns the path to the TDR_results data directory. Otherwise, it returns the system directory specified in the setup.\n\nParameters:\n\nsetup: Dict{String, Any} - The GenX settings parameters containing TimeDomainReduction and SystemFolder information.\nTDR_directory: String - The data directory where files are located.\npath: String - Path to the case folder.\n\nReturns:\n\nString: The directory path based on the setup parameters.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_inputs-Tuple{Dict, AbstractString}","page":"Inputs Functions","title":"GenX.load_inputs","text":"load_inputs(setup::Dict,path::AbstractString)\n\nLoads various data inputs from multiple input .csv files in path directory and stores variables in a Dict (dictionary) object for use in model() function\n\ninputs: setup - dict object containing setup parameters path - string path to working directory\n\nreturns: Dict (dictionary) object containing all data inputs\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Fuels-Data","page":"Inputs Functions","title":"Fuels Data","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_fuels_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_fuels_data!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_fuels_data!","text":"load_fuels_data!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to fuel costs and CO_2 content of fuels\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Generators-Input-Data","page":"Inputs Functions","title":"Generators Input Data","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_resources_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX._get_policyfile_info-Tuple{}","page":"Inputs Functions","title":"GenX._get_policyfile_info","text":"_get_policyfile_info()\n\nInternal function to get policy file information.\n\nReturns\n\npolicyfile_info (NamedTuple): A tuple containing policy file information.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX._get_resource_info-Tuple{}","page":"Inputs Functions","title":"GenX._get_resource_info","text":"_get_resource_info()\n\nInternal function to get resource information (filename and GenX type) for each type of resource available in GenX.\n\n\n\nresource_info (NamedTuple): A tuple containing resource information.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX._get_summary_map-Tuple{}","page":"Inputs Functions","title":"GenX._get_summary_map","text":"_get_summary_map()\n\nInternal function to get a map of GenX resource type their corresponding names in the summary table.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_attributes_to_resource!-Union{Tuple{T}, Tuple{GenX.AbstractResource, Vector{Symbol}, T}} where T<:DataFrames.DataFrameRow","page":"Inputs Functions","title":"GenX.add_attributes_to_resource!","text":"add_attributes_to_resource!(resource::AbstractResource, new_symbols::Vector{Symbol}, new_values::T) where T <: DataFrameRow\n\nAdds a set of new attributes (names and corresponding values) to a resource. The resource is modified in-place.\n\nArguments\n\nresource::AbstractResource: The resource to add attributes to.\nnew_symbols::Vector{Symbol}: Vector of symbols containing the names of the new attributes.\nnew_values::DataFrameRow: DataFrameRow containing the values of the new attributes.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_df_to_resources!-Tuple{Vector{<:GenX.AbstractResource}, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.add_df_to_resources!","text":"add_df_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)\n\nAdds the data contained in a DataFrame to a vector of resources. Each row in the DataFrame corresponds to a resource. If the name of the resource in the DataFrame matches a name of a resource in the model, all the columns of that DataFrameRow are added as new attributes to the corresponding resource. \n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\nmodule_in::DataFrame: The dataframe to add.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_id_to_resource_df!-Tuple{DataFrames.DataFrame, AbstractVector}","page":"Inputs Functions","title":"GenX.add_id_to_resource_df!","text":"add_id_to_resource_df!(df::DataFrame, indices::AbstractVector)\n\nAdds a new column 'id' to the DataFrame with the provided resource indices. The dataframe is modified in-place.\n\nArguments\n\ndf::DataFrame: The input DataFrame to which the indices are to be added.\nindices::AbstractVector: The array of indices to be added as a new column.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_module_to_resources!-Tuple{Vector{<:GenX.AbstractResource}, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.add_module_to_resources!","text":"add_module_to_resources!(resources::Vector{<:AbstractResource}, module_in::DataFrame)\n\nReads module dataframe and adds columns as new attributes to the resources in the model if the resource name in the module file matches a resource name in the model. The module file is assumed to have a column named \"resource\" containing the resource names.\n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\nmodule_in::DataFrame: The dataframe with the columns to add to the resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_modules_to_resources!-Tuple{Vector{<:GenX.AbstractResource}, Dict, AbstractString}","page":"Inputs Functions","title":"GenX.add_modules_to_resources!","text":"add_modules_to_resources!(resources::Vector{<:AbstractResource}, setup::Dict, resources_path::AbstractString)\n\nReads module dataframes, loops over files and adds columns as new attributes to the resources in the model.\n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\nsetup (Dict): A dictionary containing GenX settings.\nresources_path::AbstractString: The path to the resources folder.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_policies_to_resources!-Tuple{Vector{<:GenX.AbstractResource}, AbstractString}","page":"Inputs Functions","title":"GenX.add_policies_to_resources!","text":"add_policies_to_resources!(resources::Vector{<:AbstractResource}, resources_path::AbstractString)\n\nReads policy files and adds policies-related attributes to resources in the model.\n\nArguments\n\nresources::Vector{<:AbstractResource}: Vector of resources in the model.\nresources_path::AbstractString: The path to the resources folder.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_policy_to_resources!-Tuple{Vector{<:GenX.AbstractResource}, AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.add_policy_to_resources!","text":"add_policy_to_resources!(resources::Vector{<:AbstractResource}, path::AbstractString, filename::AbstractString)\n\nLoads a single policy file and adds the columns as new attributes to resources in the model if the resource name in the policy file matches a resource name in the model. The policy file is assumed to have a column named \"resource\" containing the resource names.\n\nArguments\n\nresources::Vector{<:AbstractResource}: A vector of resources.\npath::AbstractString: The path to the policy file.\nfilename::AbstractString: The name of the policy file.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.add_resources_to_input_data!-Tuple{Dict, Dict, AbstractString, Vector{<:GenX.AbstractResource}}","page":"Inputs Functions","title":"GenX.add_resources_to_input_data!","text":"add_resources_to_input_data!(inputs::Dict, setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource})\n\nAdds resources to the inputs Dict with the key \"RESOURCES\" together with sevaral sets of resource indices that are used inside GenX to construct the optimization problem. The inputs Dict is modified in-place.\n\nArguments\n\ninputs (Dict): Dictionary to store the GenX input data.\nsetup (Dict): Dictionary containing GenX settings.\ncase_path (AbstractString): Path to the case.\ngen (Vector{<:AbstractResource}): Array of GenX resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.check_mustrun_reserve_contribution-Tuple{GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.check_mustrun_reserve_contribution","text":"check_mustrun_reserve_contribution(r::AbstractResource)\n\nMake sure that a MUSTRUN resource has RegMax and Rsv_Max set to 0 (since they cannot contribute to reserves).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.check_resource-Union{Tuple{Vector{T}}, Tuple{T}} where T<:GenX.AbstractResource","page":"Inputs Functions","title":"GenX.check_resource","text":"check_resource(resources::Vector{T})::Vector{String} where T <: AbstractResource\n\nValidate the consistency of a vector of GenX resources Reports any errors/warnings as a vector of messages.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.compute_resource_indices-Tuple{DataFrames.DataFrame, Int64}","page":"Inputs Functions","title":"GenX.compute_resource_indices","text":"compute_resource_indices(resources_in::DataFrame, offset::Int64)\n\nComputes the indices for the resources loaded from a single dataframe by shifting the indices by an offset value. \n\nArguments\n\nresources_in::DataFrame: The input DataFrame containing the resources.\noffset::Int64: The offset value to be added to the indices.\n\nReturns\n\nUnitRange{Int64}: An array of indices.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.create_resource_array","page":"Inputs Functions","title":"GenX.create_resource_array","text":"create_resource_array(resource_folder::AbstractString, resources_info::NamedTuple, scale_factor::Float64=1.0)\n\nConstruct the array of resources from multiple files of different types located in the specified resource_folder. The resources_info NamedTuple contains the filename and GenX type for each type of resource available in GenX.\n\nArguments\n\nresource_folder::AbstractString: The path to the folder containing the resource files.\nresources_info::NamedTuple: A NamedTuple that maps a resource type to its filename and GenX type.\nscale_factor::Float64: A scaling factor to adjust the attributes of the resources (default: 1.0).\n\nReturns\n\nVector{<:AbstractResource}: An array of GenX resources.\n\nRaises\n\nError: If no resources data is found. Check the data path or the configuration file \"genx_settings.yml\" inside Settings.\n\n\n\n\n\n","category":"function"},{"location":"Model_Reference/load_inputs/#GenX.create_resource_array-Tuple{Dict, AbstractString}","page":"Inputs Functions","title":"GenX.create_resource_array","text":"create_resource_array(setup::Dict, resources_path::AbstractString)\n\nFunction that loads and scales resources data from folder specified in resources_path and returns an array of GenX resources.\n\nArguments\n\nsetup (Dict): Dictionary containing GenX settings.\nresources_path (AbstractString): The path to the resources folder.\n\nReturns\n\nresources (Vector{<:AbstractResource}): An array of scaled resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.create_resources_sametype-Tuple{DataFrames.DataFrame, Any}","page":"Inputs Functions","title":"GenX.create_resources_sametype","text":"create_resources_sametype(resource_in::DataFrame, ResourceType)\n\nThis function takes a DataFrame resource_in and a GenX ResourceType type, and converts the DataFrame to an array of AbstractResource of the specified type.\n\nArguments\n\nresource_in::DataFrame: The input DataFrame containing the resources belonging to a specific type.\nResourceType: The GenX type of resources to be converted to.\n\nReturns\n\nresources::Vector{ResourceType}: An array of resources of the specified type.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.dataframerow_to_dict-Tuple{DataFrames.DataFrameRow}","page":"Inputs Functions","title":"GenX.dataframerow_to_dict","text":"dataframerow_to_dict(dfr::DataFrameRow)\n\nConverts a DataFrameRow to a Dict.\n\nArguments\n\ndfr::DataFrameRow: The DataFrameRow to be converted.\n\nReturns\n\nDict: Dictionary containing the DataFrameRow data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_multi_fuels_data!-Tuple{Dict, Vector{<:GenX.AbstractResource}, Dict, AbstractString}","page":"Inputs Functions","title":"GenX.load_multi_fuels_data!","text":"load_multi_fuels_data!(inputs::Dict, gen::Vector{<:AbstractResource}, setup::Dict, path::AbstractString)\n\nFunction for reading input parameters related to multi fuels\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_resource_df-Tuple{AbstractString, Float64, Type}","page":"Inputs Functions","title":"GenX.load_resource_df","text":"load_resource_df(path::AbstractString, scale_factor::Float64, resource_type::Type)\n\nFunction to load and scale the dataframe of a given resource.\n\nArguments\n\npath::AbstractString: Path to the resource dataframe.\nscale_factor::Float64: Scaling factor for the resource data.\nresource_type::Type: GenX type of the resource.\n\nReturns\n\nresource_in::DataFrame: The loaded and scaled resource data.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_resources_data!-Tuple{Dict, Dict, AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.load_resources_data!","text":"load_resources_data!(inputs::Dict, setup::Dict, case_path::AbstractString, resources_path::AbstractString)\n\nThis function loads resources data from the resources_path folder and create the GenX data structures and add them to the inputs Dict. \n\nArguments\n\ninputs (Dict): A dictionary to store the input data.\nsetup (Dict): A dictionary containing GenX settings.\ncase_path (AbstractString): The path to the case folder.\nresources_path (AbstractString): The path to the case resources folder.\n\nRaises: DeprecationWarning: If the Generators_data.csv file is found, a deprecation warning is issued, together with an error message.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.process_piecewisefuelusage!-Tuple{Dict, Vector{<:GenX.AbstractResource}, Dict}","page":"Inputs Functions","title":"GenX.process_piecewisefuelusage!","text":"process_piecewisefuelusage!(setup::Dict, case_path::AbstractString, gen::Vector{<:AbstractResource}, inputs::Dict)\n\nReads piecewise fuel usage data from the vector of generators, create a PWFU_data that contain processed intercept and slope (i.e., heat rate) and add them to the inputs dictionary. \n\nArguments\n\nsetup::Dict: The dictionary containing the setup parameters\ncase_path::AbstractString: The path to the case folder\ngen::Vector{<:AbstractResource}: The vector of generators in the model\ninputs::Dict: The dictionary containing the input data\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.scale_columns!-Tuple{DataFrames.DataFrame, Vector{Symbol}, Float64}","page":"Inputs Functions","title":"GenX.scale_columns!","text":"scale_columns!(df::DataFrame, columns_to_scale::Vector{Symbol}, scale_factor::Float64)\n\nScales in-place the columns in columns_to_scale of a dataframe df by a scale_factor.\n\nArguments\n\ndf (DataFrame): A dataframe containing data to scale.\ncolumns_to_scale (Vector{Symbol}): A vector of column names to scale.\nscale_factor (Float64): A scaling factor for energy and currency units.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.scale_resources_data!-Tuple{DataFrames.DataFrame, Float64}","page":"Inputs Functions","title":"GenX.scale_resources_data!","text":"scale_resources_data!(resource_in::DataFrame, scale_factor::Float64)\n\nScales resources attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.\n\nArguments\n\nresource_in (DataFrame): A dataframe containing data for a specific resource.\nscale_factor (Float64): A scaling factor for energy and currency units.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.scale_vre_stor_data!-Tuple{DataFrames.DataFrame, Float64}","page":"Inputs Functions","title":"GenX.scale_vre_stor_data!","text":"scale_vre_stor_data!(vre_stor_in::DataFrame, scale_factor::Float64)\n\nScales vre_stor attributes in-place if necessary. Generally, these scalings converts energy and power units from MW to GW and /MW to M/GW. Both are done by dividing the values by 1000. See documentation for descriptions of each column being scaled.\n\nArguments\n\nvre_stor_in (DataFrame): A dataframe containing data for co-located VREs and storage.\nscale_factor (Float64): A scaling factor for energy and currency units.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.split_storage_resources!-Tuple{Dict, Vector{<:GenX.AbstractResource}}","page":"Inputs Functions","title":"GenX.split_storage_resources!","text":"split_storage_resources!(inputs::Dict, gen::Vector{<:AbstractResource})\n\nFor co-located VRE-storage resources, this function returns the storage type \t(1. long-duration or short-duration storage, 2. symmetric or asymmetric storage) for charging and discharging capacities\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.summary-Tuple{Vector{<:GenX.AbstractResource}}","page":"Inputs Functions","title":"GenX.summary","text":"summary(rs::Vector{<:AbstractResource})\n\nPrints a summary of the resources loaded into the model.\n\nArguments\n\nrs (Vector{<:AbstractResource}): An array of GenX resources.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.update_retrofit_id-Tuple{GenX.AbstractResource}","page":"Inputs Functions","title":"GenX.update_retrofit_id","text":"update_retrofit_id(r::AbstractResource)\n\nUpdates the retrofitid of a resource that can be retrofit or is a retrofit option by appending the region to the retrofitid.\n\nArguments\n\nr::AbstractResource: The resource to update.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.validate_policy_dataframe!-Tuple{AbstractString, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.validate_policy_dataframe!","text":"validate_policy_dataframe!(filename::AbstractString, policy_in::DataFrame)\n\nValidate the policy dataframe by checking if it has any attributes and if the column names are valid. The dataframe is modified in-place.\n\nArguments\n\nfilename::AbstractString: The name of the policy file.\npolicy_in::DataFrame: The policy dataframe.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.validate_policy_files-Tuple{AbstractString, Dict}","page":"Inputs Functions","title":"GenX.validate_policy_files","text":"validate_policy_files(resource_policies_path::AbstractString, setup::Dict)\n\nValidate the policy files by checking if they exist in the specified folder and if the setup flags are consistent with the files found.\n\nArguments\n\nresource_policies_path::AbstractString: The path to the policy files.\nsetup::Dict: Dictionary containing GenX settings.\n\nReturns\n\nwarning messages if the polcies are set to 1 in settings but the files are not found in the resourcepoliciespath.\n\n!isfile(joinpath(resourcepoliciespath, filename))\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Variability-of-Generators'-Outputs","page":"Inputs Functions","title":"Variability of Generators' Outputs","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_generators_variability.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_generators_variability!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_generators_variability!","text":"load_generators_variability!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to hourly maximum capacity factors for generators, storage, and flexible demand resources\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Demand-Data","page":"Inputs Functions","title":"Demand Data","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_demand_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_demand_data!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_demand_data!","text":"load_demand_data!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to electricity demand (load)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.prevent_doubled_timedomainreduction-Tuple{AbstractString}","page":"Inputs Functions","title":"GenX.prevent_doubled_timedomainreduction","text":"prevent_doubled_timedomainreduction(path::AbstractString)\n\nThis function prevents TimeDomainReduction from running on a case which already has more than one Representative Period or has more than one Sub_Weight specified.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Transmission-Network","page":"Inputs Functions","title":"Transmission Network","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_network_data.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_network_data!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_network_data!","text":"load_network_data!(setup::Dict, path::AbstractString, inputs_nw::Dict)\n\nFunction for reading input parameters related to the electricity transmission network\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_network_map_from_list-Tuple{DataFrames.DataFrame, Any, Any, Any}","page":"Inputs Functions","title":"GenX.load_network_map_from_list","text":"load_network_map_from_list(network_var::DataFrame, Z, L, list_columns)\n\nLoads the network map from a list-style interface\n\n..., Network_Lines, Start_Zone, End_Zone, ...\n 1, 1, 2,\n 2, 1, 3,\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_network_map_from_matrix-Tuple{DataFrames.DataFrame, Any, Any}","page":"Inputs Functions","title":"GenX.load_network_map_from_matrix","text":"load_network_map_from_matrix(network_var::DataFrame, Z, L)\n\nLoads the network map from a matrix-style interface\n\n..., Network_Lines, z1, z2, z3, ...\n 1, 1, -1, 0,\n 2, 1, 0, -1,\n\nThis is equivalent to the list-style interface where the zone zN with entry +1 is the starting zone of the line and the zone with entry -1 is the ending zone of the line.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Minimum-Capacity-Requirements","page":"Inputs Functions","title":"Minimum Capacity Requirements","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_minimum_capacity_requirement.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_minimum_capacity_requirement!-Tuple{AbstractString, Dict, Dict}","page":"Inputs Functions","title":"GenX.load_minimum_capacity_requirement!","text":"load_minimum_capacity_requirement!(path::AbstractString, inputs::Dict, setup::Dict)\n\nRead input parameters related to mimimum capacity requirement constraints (e.g. technology specific deployment mandates)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Capacity-Reserve-Margin","page":"Inputs Functions","title":"Capacity Reserve Margin","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_cap_reserve_margin.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_cap_reserve_margin!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_cap_reserve_margin!","text":"load_cap_reserve_margin!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to planning reserve margin constraints\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_cap_reserve_margin_trans!-Tuple{Dict, Dict, DataFrames.DataFrame}","page":"Inputs Functions","title":"GenX.load_cap_reserve_margin_trans!","text":"load_cap_reserve_margin_trans!(setup::Dict, inputs::Dict, network_var::DataFrame)\n\nRead input parameters related to participation of transmission imports/exports in capacity reserve margin constraint.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#CO_2-Emissions-Cap","page":"Inputs Functions","title":"CO_2 Emissions Cap","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_co2_cap.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_co2_cap!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_co2_cap!","text":"load_co2_cap!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to CO_2 emissions cap constraints\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Energy-Share-Requirement","page":"Inputs Functions","title":"Energy Share Requirement","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_energy_share_requirement.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_energy_share_requirement!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_energy_share_requirement!","text":"load_energy_share_requirement!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to mimimum energy share requirement constraints (e.g. renewable portfolio standard or clean electricity standard policies)\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Mapping-Representative-Time-Periods","page":"Inputs Functions","title":"Mapping Representative Time Periods","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_period_map.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_period_map!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_period_map!","text":"load_period_map!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to mapping of representative time periods to full chronological time series\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Variability-of-the-Solar-PV-and-Wind-Components'-Outputs-(for-Co-located-Storage-Resources)","page":"Inputs Functions","title":"Variability of the Solar PV and Wind Components' Outputs (for Co-located Storage Resources)","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_vre_stor_variability.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.load_vre_stor_variability!-Tuple{Dict, AbstractString, Dict}","page":"Inputs Functions","title":"GenX.load_vre_stor_variability!","text":"load_vre_stor_variability!(setup::Dict, path::AbstractString, inputs::Dict)\n\nRead input parameters related to hourly maximum capacity factors for the solar PV \t(DC capacity factors) component and wind (AC capacity factors) component of co-located \tgenerators\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#Functions-for-developers","page":"Inputs Functions","title":"Functions for developers","text":"","category":"section"},{"location":"Model_Reference/load_inputs/#Standardized-loading-of-dataframes-from-CSV-files","page":"Inputs Functions","title":"Standardized loading of dataframes from CSV files","text":"","category":"section"},{"location":"Model_Reference/load_inputs/","page":"Inputs Functions","title":"Inputs Functions","text":"Modules = [GenX]\nPages = [\"load_dataframe.jl\"]","category":"page"},{"location":"Model_Reference/load_inputs/#GenX.extract_matrix_from_dataframe-Tuple{DataFrames.DataFrame, AbstractString}","page":"Inputs Functions","title":"GenX.extract_matrix_from_dataframe","text":"extract_matrix_from_dataframe(df::DataFrame, columnprefix::AbstractString)\n\nFinds all columns in the dataframe which are of the form columnprefix_[Integer], and extracts them in order into a matrix. The function also checks that there's at least one column with this prefix, and that all columns numbered from 1...N exist.\n\nThis is now acceptable:\n\nESR_1, other_thing, ESR_3, ESR_2,\n 0.1, 1, 0.3, 0.2,\n 0.4, 2, 0.6, 0.5,\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.file_exists-Tuple{Any, Vector{String}}","page":"Inputs Functions","title":"GenX.file_exists","text":"file_exists(dir::AbstractString, basenames::Vector{String})::Bool\n\nChecks that a file exists in a directory under (at least) one of a list of 'aliases'.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_dataframe-Tuple{AbstractString, AbstractString}","page":"Inputs Functions","title":"GenX.load_dataframe","text":"load_dataframe(dir::AbstractString, base::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given directory and file name. If not found immediately, look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.load_dataframe-Tuple{AbstractString}","page":"Inputs Functions","title":"GenX.load_dataframe","text":"load_dataframe(path::AbstractString)\n\nAttempts to load a dataframe from a csv file with the given path. If it's not found immediately, it will look for files with a different case (lower/upper) in the file's basename.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/load_inputs/#GenX.validate_df_cols-Tuple{DataFrames.DataFrame, AbstractString, Any}","page":"Inputs Functions","title":"GenX.validate_df_cols","text":"validate_df_cols(df::DataFrame, df_name::AbstractString, required_cols::Vector{AbstractString})\n\nCheck that the dataframe has all the required columns.\n\nArguments\n\ndf::DataFrame: the dataframe to check\ndf_name::AbstractString: the name of the dataframe, for error messages\nrequired_cols::Vector{AbstractString}: the names of the required columns\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/Resources/electrolyzers/#Hydrogen-Electrolyzers","page":"Hydrogen Electrolyzers","title":"Hydrogen Electrolyzers","text":"","category":"section"},{"location":"Model_Reference/Resources/electrolyzers/","page":"Hydrogen Electrolyzers","title":"Hydrogen Electrolyzers","text":"Modules = [GenX]\nPages = [\"electrolyzer.jl\"]","category":"page"},{"location":"Model_Reference/Resources/electrolyzers/#GenX.electrolyzer!-Tuple{JuMP.Model, Dict, Dict}","page":"Hydrogen Electrolyzers","title":"GenX.electrolyzer!","text":"electrolyzer!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the expressions and constraints for operation of hydrogen electrolyzers (y in mathcalEL subseteq mathcalG). \tThis is a basic implementation of hydrogen electrolyzers that allows the specification of an hourly clean supply constraint. \tFor a richer formulation, please see the DOLPHYN code at https://github.com/macroenergy/DOLPHYN.\n\nExpressions\n\nConsumption of electricity by electrolyzer y in time t, denoted by Pi_yz, is subtracted from power balance expression ePowerBalance (as per other demands or battery charging) and added to Energy Share Requirement policy balance (if applicable), eESR.\n\nRevenue from hydrogen production by each electrolyzer y, equal to omega_t times Pi_yt eta^electrolyzer_y times ^{hydrogen}y$, is subtracted from the objective function, where \\eta^{electrolyzer}y$ is the efficiency of the electrolyzer y in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced and ^{hydrogen}_y$ is the price of hydrogen per metric tonne for electrolyzer y.\n\nRamping limits\n\nElectrolyzers adhere to the following ramping limits on hourly changes in power output:\n\nbeginaligned\n\tPi_yt-1 - Pi_yt leq kappa_y^down Delta^texttotal_y hspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\nbeginaligned\n\tPi_yt - Pi_yt-1 leq kappa_y^up Delta^texttotal_y hspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\n(See Constraints 1-2 in the code)\n\nThis set of time-coupling constraints wrap around to ensure the power output in the first time step of each year (or each representative period), t in mathcalT^start, is within the eligible ramp of the power output in the final time step of the year (or each representative period), t+tau^period-1.\n\nMinimum and maximum power output\n\nElectrolyzers are bound by the following limits on maximum and minimum power output:\n\nbeginaligned\n\tPi_yt geq rho^min_y times Delta^total_y\n\thspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\nbeginaligned\n\tTheta_yt leq rho^max_yt times Pi_^total_y\n\thspace1cm forall y in mathcalEL forall t in mathcalT\nendaligned\n\n(See Constraints 3-4 in the code)\n\nMinimum annual hydrogen production\n\nThe sum of annual hydrogen production by each electrolyzer y in mathcalEL must exceed a minimum quantity specified in inputs:\n\nbeginaligned\n\tsum_t in T (omega_t times Pi_yt eta^electrolyzer_y) geq mathcalMin kt_y times 10^3\n\thspace1cm forall y in mathcalEL\nendaligned\n\nwhere eta^electrolyzer_y is the efficiency of the electrolyzer y in megawatt-hours (MWh) of electricity per metric tonne of hydrogen produced and mathcalMin kt_y is the minimum annual quantity of hydrogen that must be produced by electrolyzer y in kilotonnes. (See constraint 5 in the code)\n\nHourly clean supply matching constraint\n\nThis optional constraint (enabled by setting HydrogenHourlyMatching==1 in genx_settings.yml) requires generation from qualified resources (y in mathcalQualified, indicated by Qualified_Hydrogen_Supply==1 in the resource .csv files) from within the same zone z as the electrolyzers are located to be >= hourly consumption from electrolyzers in the zone (and any charging by qualified storage within the zone used to help increase electrolyzer utilization):\n\nbeginaligned\n\tsum_y in z cap mathcalQualified Theta_yt geq sum_y in z cap mathcalEL Pi_yt + sum_y in z cap mathcalQualified cap mathcalSTOR Pi_yt\n\thspace1cm forall z in mathcalZ forall t in mathcalT\nendaligned\n\n(See constraint 6 in the code)\n\nThis constraint permits modeling of the 'three pillars' requirements for clean hydrogen supply of (1) new clean supply (if only new clean resources are designated as eligible), (2) that is deliverable to the electrolyzer (assuming co-location within the same modeled zone = deliverability), and (3) produced within the same hour as the electrolyzer consumes power (otherwise known as 'additionality/new supply', 'deliverability', and 'temporal matching requirements') See Ricks, Xu & Jenkins (2023), ''Minimizing emissions from grid-based hydrogen production in the United States'' Environ. Res. Lett. 18 014025 doi:10.1088/1748-9326/acacb5 for more.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Core","page":"Core","title":"Core","text":"","category":"section"},{"location":"Model_Reference/core/#Discharge","page":"Core","title":"Discharge","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"discharge.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.discharge!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.discharge!","text":"discharge!(EP::Model, inputs::Dict, setup::Dict)\n\nThis module defines the power decision variable Theta_yt forall y in mathcalG t in mathcalT, representing energy injected into the grid by resource y by at time period t. This module additionally defines contributions to the objective function from variable costs of generation (variable O&M) from all resources y in mathcalG over all time periods t in mathcalT:\n\nbeginaligned\n\tObj_Var_gen =\n\tsum_y in mathcalG sum_t in mathcalTomega_ttimes(pi^VOM_y)times Theta_yt\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.investment_discharge!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.investment_discharge!","text":"investment_discharge!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the expressions and constraints keeping track of total available power generation/discharge capacity across all resources as well as constraints on capacity retirements. The total capacity of each resource is defined as the sum of the existing capacity plus the newly invested capacity minus any retired capacity. Note for storage and co-located resources, additional energy and charge power capacity decisions and constraints are defined in the storage and co-located VRE and storage module respectively.\n\nbeginaligned\n Delta^total_yz =(overlineDelta_yz+Omega_yz-Delta_yz) forall y in mathcalG z in mathcalZ\nendaligned\n\nOne cannot retire more capacity than existing capacity.\n\nbeginaligned\nDelta_yz leq overlineDelta_yz\n\thspace4 cm forall y in mathcalG z in mathcalZ\nendaligned\n\nFor resources where overlineOmega_yz and underlineOmega_yz is defined, then we impose constraints on minimum and maximum power capacity.\n\nbeginaligned\n Delta^total_yz leq overlineOmega_yz\n\thspace4 cm forall y in mathcalG z in mathcalZ \n Delta^total_yz geq underlineOmega_yz\n\thspace4 cm forall y in mathcalG z in mathcalZ\nendaligned\n\nIn addition, this function adds investment and fixed O\\&M related costs related to discharge/generation capacity to the objective function:\n\nbeginaligned\n \tsum_y in mathcalG sum_z in mathcalZ\n\tleft( (pi^INVEST_yz times overlineOmega^size_yz times Omega_yz)\n\t+ (pi^FOM_yz times overlineOmega^size_yz times Delta^total_yz)right)\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.write_multi_stage_capacities_discharge-Tuple{String, Dict}","page":"Core","title":"GenX.write_multi_stage_capacities_discharge","text":"write_multi_stage_capacities_discharge(outpath::String, settings_d::Dict)\n\nThis function writes the file capacities_multi_stage.csv to the Results directory. This file contains starting resource capacities from the first model stage and end resource capacities for the first and all subsequent model stages.\n\ninputs:\n\noutpath – String which represents the path to the Results directory.\nsettings_d - Dictionary containing settings dictionary configured in the multi-stage settings file multi_stage_settings.yml.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.write_virtual_discharge-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Core","title":"GenX.write_virtual_discharge","text":"write_virtual_discharge(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for writing the \"virtual\" discharge of each storage technology. Virtual discharge is used to \tallow storage resources to contribute to the capacity reserve margin without actually discharging.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Non-served-Energy","page":"Core","title":"Non-served Energy","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"non_served_energy.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.non_served_energy!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.non_served_energy!","text":"non_served_energy!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function defines the non-served energy/curtailed demand decision variable Lambda_stz forall s in mathcalS forall t in mathcalT z in mathcalZ, representing the total amount of demand curtailed in demand segment s at time period t in zone z. The first segment of non-served energy, s=1, is used to denote the cost of involuntary demand curtailment (e.g. emergency load shedding or rolling blackouts), specified as the value of n_1^slope. Additional segments, s geq 2 can be used to specify a segment-wise approximation of a price elastic demand curve, or segments of price-responsive curtailable demands (aka demand response). Each segment denotes a price/cost at which the segment of demand is willing to curtail consumption, n_s^slope, representing the marginal willingness to pay for electricity of this segment of demand (or opportunity cost incurred when demand is not served) and a maximum quantity of demand in this segment, n_s^size, specified as a share of demand in each zone in each time step, D_tz Note that the current implementation assumes demand segments are an equal share of hourly demand in all zones. This function defines contributions to the objective function from the cost of non-served energy/curtailed demand from all demand curtailment segments s in mathcalS over all time periods t in mathcalT and all zones z in mathcalZ:\n\nbeginaligned\n\tObj_NSE =\n\tsum_s in mathcalS sum_t in mathcalT sum_z in mathcalZomega_t times n_s^slope times Lambda_stz\nendaligned\n\nContributions to the power balance expression from non-served energy/curtailed demand from each demand segment s in mathcalS are also defined as:\n\nbeginaligned\n\tPowerBal_NSE =\n\tsum_s in mathcalS Lambda_stz\n\t\thspace4 cm forall s in mathcalS t in mathcalT\nendaligned\n\nBounds on curtailable demand Demand curtailed in each segment of curtailable demands s in mathcalS cannot exceed a maximum allowable share of demand:\n\nbeginaligned\n\tLambda_stz leq (n_s^size times D_tz)\n\thspace4 cm forall s in mathcalS t in mathcalT zin mathcalZ\nendaligned\n\nAdditionally, total demand curtailed in each time step cannot exceed total demand:\n\nbeginaligned\n\tsum_s in mathcalS Lambda_stz leq D_tz\n\thspace4 cm forall t in mathcalT zin mathcalZ\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Operational-Reserves","page":"Core","title":"Operational Reserves","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"operational_reserves.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.load_operational_reserves!-Tuple{Dict, AbstractString, Dict}","page":"Core","title":"GenX.load_operational_reserves!","text":"load_operational_reserves!(setup::Dict,path::AbstractString, inputs::Dict)\n\nRead input parameters related to frequency regulation and operating reserve requirements\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.operational_reserves!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.operational_reserves!","text":"operational_reserves!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function sets up reserve decisions and constraints, using the operationalreservescore()and operational_reserves_contingency() functions.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.operational_reserves_contingency!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.operational_reserves_contingency!","text":"operational_reserves_contingency!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function establishes several different versions of contingency reserve requirement expression, CONTINGENCY used in the operationalreservescore() function below.\n\nContingency operational reserves represent requirements for upward ramping capability within a specified time frame to compensated for forced outages or unplanned failures of generators or transmission lines (e.g. N-1 contingencies).\n\nThere are three options for the Contingency expression, depending on user settings: \t1. a static contingency, in which the contingency requirement is set based on a fixed value (in MW) specified in the '''Operational_reserves.csv''' input file; \t2. a dynamic contingency based on installed capacity decisions, in which the largest 'installed' generator is used to determine the contingency requirement for all time periods; and \t3. dynamic unit commitment based contingency, in which the largest 'committed' generator in any time period is used to determine the contingency requirement in that time period.\n\nNote that the two dynamic contigencies are only available if unit commitment is being modeled.\n\nStatic contingency Option 1 (static contingency) is expressed by the following constraint:\n\nbeginaligned\n\tContingency = epsilon^contingency\nendaligned\n\nwhere epsilon^contingency is static contingency requirement in MWs.\n\nDynamic capacity-based contingency Option 2 (dynamic capacity-based contingency) is expressed by the following constraints:\n\nbeginaligned\n\tContingency geq Omega^size_yz times alpha^ContingencyAux_yz forall y in mathcalUC z in mathcalZ\n\talpha^ContingencyAux_yz leq Delta^texttotal_yz forall y in mathcalUC z in mathcalZ\n\talpha^ContingencyAux_yz geq M_y times Delta^texttotal_yz forall y in mathcalUC z in mathcalZ\nendaligned\n\nwhere M_y is a `big M' constant equal to the largest possible capacity that can be installed for generation cluster y, and alpha^ContingencyAux_yz in 01 is a binary auxiliary variable that is forced by the second and third equations above to be 1 if the total installed capacity Delta^texttotal_yz 0 for any generator y in mathcalUC and zone z, and can be 0 otherwise. Note that if the user specifies contingency option 2, and is also using the linear relaxation of unit commitment constraints, the capacity size parameter for units in the set mathcalUC must still be set to a discrete unit size for this contingency to work as intended.\n\nDynamic commitment-based contingency Option 3 (dynamic commitment-based contingency) is expressed by the following set of constraints:\n\nbeginaligned\n\t Contingency geq Omega^size_yz times Contingency_Aux_yzt forall y in mathcalUC z in mathcalZ\n\t Contingency_Aux_yzt leq nu_yzt forall y in mathcalUC z in mathcalZ\n\t Contingency_Aux_yzt geq M_y times nu_yzt forall y in mathcalUC z in mathcalZ\nendaligned\n\nwhere M_y is a `big M' constant equal to the largest possible capacity that can be installed for generation cluster y, and Contingency_Aux_yzt in 01 is a binary auxiliary variable that is forced by the second and third equations above to be 1 if the commitment state for that generation cluster nu_yzt 0 for any generator y in mathcalUC and zone z and time period t, and can be 0 otherwise. Note that this dynamic commitment-based contingency can only be specified if discrete unit commitment decisions are used (e.g. it will not work if relaxed unit commitment is used).\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.operational_reserves_core!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.operational_reserves_core!","text":"operational_reserves_core!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates decision variables related to frequency regulation and reserves provision and constraints setting overall system requirements for regulation and operating reserves.\n\nRegulation and reserves decisions f_ytz geq 0 is the contribution of generation or storage resource y in Y in time t in T and zone z in Z to frequency regulation\n\nr_ytz geq 0\n\nis the contribution of generation or storage resource y in Y in time t in T and zone z in Z to operating reserves up\n\nWe assume frequency regulation is symmetric (provided in equal quantity towards both upwards and downwards regulation). To reduce computational complexity, operating reserves are only modeled in the upwards direction, as downwards reserves requirements are rarely binding in practice.\n\nStorage resources (y in mathcalO) have two pairs of auxilary variables to reflect contributions to regulation and reserves when charging and discharging, where the primary variables (f_yzt \\& r_yzt) becomes equal to sum of these auxilary variables.\n\nCo-located VRE-STOR resources are described further in the reserves function for colocated VRE and storage resources (vre_stor_operational_reserves!()).\n\nUnmet operating reserves\n\nunmet_rsv_t geq 0\n\ndenotes any shortfall in provision of operating reserves during each time period t in T\n\nThere is a penalty C^rsv added to the objective function to penalize reserve shortfalls, equal to:\n\nbeginaligned\n\tC^rvs = sum_t in T omega_t times unmet_rsv_t\nendaligned\n\nFrequency regulation requirements\n\nTotal requirements for frequency regulation (aka primary reserves) in each time step t are specified as fractions of hourly demand (to reflect demand forecast errors) and variable renewable avaialblity in the time step (to reflect wind and solar forecast errors).\n\nbeginaligned\n sum_y in Y z in Z f_ytz geq epsilon^demand_reg times sum_z in Z mathcalD_zt + epsilon^vre_reg times (sum_z in Z rho^max_yzt times Delta^texttotal_yz \n + sum_z in Z rho^maxpv_yzt times Delta^texttotalpv_yz + sum_z in Z rho^maxwind_yzt times Delta^texttotalwind_yz) quad forall t in T\nendaligned\n\nwhere mathcalD_zt is the forecasted electricity demand in zone z at time t (before any demand flexibility); rho^max_yzt is the forecasted capacity factor for standalone variable renewable resources y in VRE and zone z in time step t; rho^maxpv_yzt is the forecasted capacity factor for co-located solar PV resources y in mathcalVS^pv and zone z in time step t; rho^maxwind_yzt is the forecasted capacity factor for co-located wind resources y in mathcalVS^pv and zone z in time step t; Delta^texttotalpv_yz is the total installed capacity of co-located solar PV resources y in mathcalVS^pv and zone z; Delta^texttotalwind_yz is the total installed capacity of co-located wind resources y in mathcalVS^wind and zone z; and epsilon^demand_reg and epsilon^vre_reg are parameters specifying the required frequency regulation as a fraction of forecasted demand and variable renewable generation.\n\nOperating reserve requirements\n\nTotal requirements for operating reserves in the upward direction (aka spinning reserves or contingency reserces or secondary reserves) in each time step t are specified as fractions of time step's demand (to reflect demand forecast errors) and variable renewable avaialblity in the time step (to reflect wind and solar forecast errors) plus the largest planning contingency (e.g. potential forced generation outage).\n\nbeginaligned\n\t sum_y in Y z in Z r_yzt + r^unmet_t geq epsilon^demand_rsv times sum_z in Z mathcalD_zt + epsilon^vre_rsv times (sum_z in Z rho^max_yzt times Delta^texttotal_yz \n\t + sum_z in Z rho^maxpv_yzt times Delta^texttotalpv_yz + sum_z in Z rho^maxwind_yzt times Delta^texttotalwind_yz) + Contingency quad forall t in T\nendaligned\n\nwhere mathcalD_zt is the forecasted electricity demand in zone z at time t (before any demand flexibility); rho^max_yzt is the forecasted capacity factor for standalone variable renewable resources y in VRE and zone z in time step t; rho^maxpv_yzt is the forecasted capacity factor for co-located solar PV resources y in mathcalVS^pv and zone z in time step t; rho^maxwind_yzt is the forecasted capacity factor for co-located wind resources y in mathcalVS^wind and zone z in time step t; Delta^texttotal_yz is the total installed capacity of standalone variable renewable resources y in VRE and zone z; Delta^texttotalpv_yz is the total installed capacity of co-located solar PV resources y in mathcalVS^pv and zone z; Delta^texttotalwind_yz is the total installed capacity of co-located wind resources y in mathcalVS^wind and zone z; and epsilon^demand_rsv and epsilon^vre_rsv are parameters specifying the required contingency reserves as a fraction of forecasted demand and variable renewable generation. Contingency is an expression defined in the operational_reserves_contingency!() function meant to represent the largest N-1 contingency (unplanned generator outage) that the system operator must carry operating reserves to cover and depends on how the user wishes to specify contingency requirements.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Transmission","page":"Core","title":"Transmission","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"transmission.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.dcopf_transmission!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.dcopf_transmission!","text":"function dcopf_transmission!(EP::Model, inputs::Dict, setup::Dict)\n\nThe addtional constraints imposed upon the line flows in the case of DC-OPF are as follows: For the definition of the line flows, in terms of the voltage phase angles:\n\nbeginaligned\n Phi_lt=mathcalB_l times (sum_zin mathcalZ(varphi^map_lz times theta_zt)) quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nFor imposing the constraint of maximum allowed voltage phase angle difference across lines:\n\nbeginaligned\n sum_zin mathcalZ(varphi^map_lz times theta_zt) leq Delta theta^max_l quad forall l in mathcalL forall t in mathcalT\n\t sum_zin mathcalZ(varphi^map_lz times theta_zt) geq -Delta theta^max_l quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nFinally, we enforce the reference voltage phase angle constraint:\n\nbeginaligned\ntheta_1t = 0 quad forall t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.investment_transmission!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.investment_transmission!","text":"function investment_transmission!(EP::Model, inputs::Dict, setup::Dict)\n The function model transmission expansion and adds transmission reinforcement or construction costs to the objective function. Transmission reinforcement costs are equal to the sum across all lines of the product between the transmission reinforcement/construction cost, $pi^{TCAP}_{l}$, times the additional transmission capacity variable, $\\bigtriangleup\\varphi^{cap}_{l}$.\n ```math\n \\begin{aligned}\n & \\sum_{l \\in \\mathcal{L}}\\left(\\pi^{TCAP}_{l} \\times \\bigtriangleup\\varphi^{cap}_{l}\\right)\n \\end{aligned}\n ```\n Note that fixed O\\&M and replacement capital costs (depreciation) for existing transmission capacity is treated as a sunk cost and not included explicitly in the GenX objective function.\n **Accounting for Transmission Between Zones**\n Available transmission capacity between zones is set equal to the existing line's maximum power transfer capacity, $\\overline{\\varphi^{cap}_{l}}$, plus any transmission capacity added on that line (for lines eligible for expansion in the set $\\mathcal{E}$). \n \\begin{aligned}\n &\\varphi^{cap}_{l} = \\overline{\\varphi^{cap}_{l}} , &\\quad \\forall l \\in (\\mathcal{L} \\setminus \\mathcal{E} ),\\forall t \\in \\mathcal{T}\\\\\n % trasmission expansion\n &\\varphi^{cap}_{l} = \\overline{\\varphi^{cap}_{l}} + \\bigtriangleup\\varphi^{cap}_{l} , &\\quad \\forall l \\in \\mathcal{E},\\forall t \\in \\mathcal{T} \n \\end{aligned}\n The additional transmission capacity, $\\bigtriangleup\\varphi^{cap}_{l} $, is constrained by a maximum allowed reinforcement, $\\overline{\\bigtriangleup\\varphi^{cap}_{l}}$, for each line $l \\in \\mathcal{E}$.\n \\begin{aligned}\n & \\bigtriangleup\\varphi^{cap}_{l} \\leq \\overline{\\bigtriangleup\\varphi^{cap}_{l}}, &\\quad \\forall l \\in \\mathcal{E}\n \\end{aligned}\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.transmission!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.transmission!","text":"transmission!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function establishes decisions, expressions, and constraints related to transmission power flows between model zones and associated transmission losses (if modeled).\n\nPower flow and transmission loss terms are also added to the power balance constraint for each zone:\n\nbeginaligned\n\t- sum_lin mathcalL(varphi^map_lz times Phi_lt) - frac12 sum_lin mathcalL(varphi^map_lz times beta_lt(cdot))\nendaligned\n\nPower flows, Phi_lt, on each line l into or out of a zone (defined by the network map varphi^map_lz), are considered in the demand balance equation for each zone. By definition, power flows leaving their reference zone are positive, thus the minus sign is used for this term. Losses due to power flows increase demand, and one-half of losses across a line linking two zones are attributed to each connected zone. The losses function beta_lt(cdot) will depend on the configuration used to model losses (see below). Accounting for Transmission Between Zones Power flow, Phi_lt, on each line (or more likely a `path' aggregating flows across multiple parallel lines) is constrained to be less than or equal to the line's power transfer capacity, varphi^cap_l, plus any transmission capacity added on that line (for lines eligible for expansion in the set mathcalE). The additional transmission capacity, bigtriangleupvarphi^cap_l is constrained by a maximum allowed reinforcement overlinebigtriangleupvarphi^cap_l, for each line l in mathcalE.\n\nbeginaligned\n\t trasmission constraints\n\t-varphi^cap_l leq Phi_lt leq varphi^cap_l quad forall l in mathcalLforall t in mathcalT\nendaligned\n\nAccounting for Transmission Losses Transmission losses due to power flows can be accounted for in three different ways. The first option is to neglect losses entirely, setting the value of the losses function to zero for all lines at all hours. The second option is to assume that losses are a fixed percentage, varphi^loss_l, of the magnitude of power flow on each line, mid Phi_lt mid (e.g., losses are a linear function of power flows). Finally, the third option is to calculate losses, ell_lt, by approximating a quadratic-loss function of power flow across the line using a piecewise-linear function with total number of segments equal to the size of the set mathcalM.\n\nbeginaligned\nconfigurable losses formulation\n\t beta_lt(cdot) = begincases 0 textif textlosses0 varphi^loss_ltimes mid Phi_lt mid textif textlosses1 ell_lt textif textlosses2 endcases quad forall l in mathcalLforall t in mathcalT\nendaligned\n\nFor the second option, an absolute value approximation is utilized to calculate the magnitude of the power flow on each line (reflecting the fact that negative power flows for a line linking nodes i and j represents flows from node j to i and causes the same magnitude of losses as an equal power flow from i to j). This absolute value function is linearized such that the flow in the line must be equal to the subtraction of the auxiliary variable for flow in the positive direction, Phi^+_lt, and the auxiliary variable for flow in the negative direction, Phi^+_lt, of the line. Then, the magnitude of the flow is calculated as the sum of the two auxiliary variables. The sum of positive and negative directional flows are also constrained by the line flow capacity.\n\nbeginaligned\n trasmission losses simple\n\tPhi_lt = Phi^+_lt - Phi^-_lt quad forall l in mathcalL forall t in mathcalT\n\tmid Phi_lt mid = Phi^+_lt + Phi^-_lt quad forall l in mathcalL forall t in mathcalT\n\tPhi^+_lt + Phi^-_lt leq varphi^cap_l quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nIf discrete unit commitment decisions are modeled, ``phantom losses'' can be observed wherein the auxiliary variables for flows in both directions (Phi^+_lt and Phi^-_lt) are both increased to produce increased losses so as to avoid cycling a thermal generator and incurring start-up costs or opportunity costs related to minimum down times. This unrealistic behavior can be eliminated via inclusion of additional constraints and a set of auxiliary binary variables, ON^+_lt in 01 forall l in mathcalL. Then the following additional constraints are created:\n\nbeginaligned\n\tPhi^+_lt leq TransON^+_lt quad forall l in mathcalL forall t in mathcalT\n\tPhi^-_lt leq varphi^cap_l -TransON^+_lt quad forall l in mathcalL forall t in mathcalT\nendaligned\n\nwhere TransON^+_lt is a continuous variable, representing the product of the binary variable ON^+_lt and the expression, varphi^cap_l. This product cannot be defined explicitly, since it will lead to a bilinear expression involving two variables. Instead, we enforce this definition via the Glover's Linearization as shown below (also referred McCormick Envelopes constraints for bilinear expressions, which is exact when one of the variables is binary).\n\nbeginaligned\n\tTransON^+_lt leq (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) times TransON^+_lt quad forall l in mathcalL forall t in mathcalT \n\tTransON^+_lt leq varphi^cap_l quad forall l in mathcalL forall t in mathcalT \n\tTransON^+_lt geq varphi^cap_l - (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) times(1- TransON^+_lt) quad forall l in mathcalL forall t in mathcalT \nendaligned\n\nThese constraints permit only the positive or negative auxiliary flow variables to be non-zero at a given time period, not both. For the third option, losses are calculated as a piecewise-linear approximation of a quadratic function of power flows. In order to do this, we represent the absolute value of the line flow variable by the sum of positive stepwise flow variables (mathcalS^+_mlt mathcalS^-_mlt), associated with each partition of line losses computed using the corresponding linear expressions. This can be understood as a segmentwise linear fitting (or first order approximation) of the quadratic losses function. The first constraint below computes the losses a the accumulated sum of losses for each linear stepwise segment of the approximated quadratic function, including both positive domain and negative domain segments. A second constraint ensures that the stepwise variables do not exceed the maximum size per segment. The slope and maximum size for each segment are calculated as per the method in \\cite{Zhang2013}.\n\nbeginaligned\n\t ell_lt = fracvarphi^ohm_l(varphi^volt_l)^2bigg( sum_m in mathcalM( S^+_mltimes mathcalS^+_mlt + S^-_mltimes mathcalS^-_mlt) bigg) quad forall l in mathcalL forall t in mathcalT \n\t textquad Where \n\t quad S^+_ml = frac2+4 times sqrt2times (m-1)1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) quad forall m in 1 colon M l in mathcalL \n\t quad S^-_ml = frac2+4 times sqrt2times (m-1)1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) quad forall m in 1 colon M l in mathcalL\n\t \n\t mathcalS^+_mlt mathcalS^-_mlt = overlinemathcalS_ml quad forall m in 1M l in mathcalL t in mathcalT \n\t textquad Where \n\t quad overlineS_lz = begincases frac(1+sqrt2)1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) textif m = 1 \n\tfrac2 times sqrt2 1+sqrt2 times (2 times M-1) (overlinevarphi^cap_l + overlinebigtriangleupvarphi^cap_l) textif m 1 endcases\nendaligned\n\nNext, a constraint ensures that the sum of auxiliary segment variables (m geq 1) minus the \"zero\" segment (which allows values to go into the negative domain) from both positive and negative domains must total the actual power flow across the line, and a constraint ensures that the sum of negative and positive flows do not exceed the flow capacity of the line.\n\nbeginaligned\n\tsum_m in 1M (mathcalS^+_mlt) - mathcalS^+_0lt = Phi_lt quad forall l in mathcalL forall t in mathcalT\n\tsum_m in 1M (mathcalS^-_mlt) - mathcalS^-_0lt = - Phi_lt\nendaligned\n\nAs with losses option 2, this segment-wise approximation of a quadratic loss function also permits 'phantom losses' to avoid cycling thermal units when discrete unit commitment decisions are modeled. In this case, the additional constraints below are also added to ensure that auxiliary segments variables do not exceed maximum value per segment and that they are filled in order; i.e., one segment cannot be non-zero unless prior segment is at its maximum value. Binary constraints deal with absolute value of power flow on each line. If the flow is positive, mathcalS^+_0lt must be zero; if flow is negative, mathcalS^+_0lt must be positive and takes on value of the full negative flow, forcing all mathcalS^+_mlt other segments (m geq 1) to be zero. Conversely, if the flow is negative, mathcalS^-_0lt must be zero; if flow is positive, mathcalS^-_0lt must be positive and takes on value of the full positive flow, forcing all mathcalS^-_mlt other segments (m geq 1) to be zero. Requiring segments to fill in sequential order and binary variables to ensure variables reflect the actual direction of power flows are both necessary to eliminate ``phantom losses'' from the solution. These constraints and binary decisions are ommited if the model is fully linear.\n\nbeginaligned\n\tmathcalS^+_mlt = overlinemathcalS_ml times ON^+_mlt quad forall m in 1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^-_mlt = overlinemathcalS_ml times ON^-_mlt quad forall m in1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^+_mlt geq ON^+_m+1lt times overlinemathcalS_ml quad forall m in 1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^-_mlt geq ON^-_m+1lt times overlinemathcalS_ml quad forall m in 1M forall l in mathcalL forall t in mathcalT\n\tmathcalS^+_0lt leq varphi^max_l times (1- ON^+_1lt) quad forall l in mathcalL forall t in mathcalT\n\tmathcalS^-_0lt leq varphi^max_l times (1- ON^-_1lt) quad forall l in mathcalL forall t in mathcalT\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Unit-Commitment","page":"Core","title":"Unit Commitment","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"ucommit.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.ucommit!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.ucommit!","text":"ucommit!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates decision variables and cost expressions associated with thermal plant unit commitment or start-up and shut-down decisions (cycling on/off)\n\nUnit commitment decision variables:\n\nThis function defines the following decision variables:\n\nnu_ytz\n\ndesignates the commitment state of generator cluster y in zone z at time t; chi_ytz represents number of startup decisions in cluster y in zone z at time t; zeta_ytz represents number of shutdown decisions in cluster y in zone z at time t.\n\nCost expressions:\n\nThe total cost of start-ups across all generators subject to unit commitment (y in UC) and all time periods, t is expressed as:\n\nbeginaligned\n\tC^start = sum_y in UC t in T omega_t times start_cost_yt times chi_yt\nendaligned\n\nThe sum of start-up costs is added to the objective function.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#CO2","page":"Core","title":"CO2","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"co2.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.co2!-Tuple{JuMP.Model, Dict}","page":"Core","title":"GenX.co2!","text":"co2!(EP::Model, inputs::Dict)\n\nThis function creates expressions to account for CO2 emissions as well as captured and sequestrated CO2 from thermal generators. It also has the capability to model the negative CO2 emissions from bioenergy with carbon capture and storage. \n\n***** Expressions *****\n\nFor thermal generators which combust fuels (e.g., coal, natural gas, and biomass), the net CO2 emission to the environment is a function of fuel consumption, CO2 emission factor, CO2 capture fraction, and whether the feedstock is biomass. Biomass is a factor in this equation because biomass generators are assumed to generate zero net CO2 emissions, or negative net CO2 emissions in the case that the CO2 they emit is captured and sequestered underground.\n\nIf a user wishes to represent a generator that combusts biomass, then in the resource .csv files, the \"Biomass\" column (boolean, 1 or 0), which represents if a generator y uses biomass or not, should be set to 1. The CO2 emissions from such a generator will be assumed to be zero without CCS and negative with CCS.\n\nThe CO2 emissions from generator y at time t are determined by total fuel consumption (MMBTU) multiplied by the CO2 content of the fuel (tCO2/MMBTU), and by (1 - Biomass [0 or 1] - CO2 capture fraction [a fraction, between 0 - 1]). The CO2 capture fraction could be differernt during the steady-state and startup events (generally startup events have a lower CO2 capture fraction), so we use distinct CO2 capture fractions to determine the emissions. In short, the CO2 emissions for a generator depend on the CO2 emission factor from fuel combustion, the CO2 capture fraction, and whether the generator uses biomass.\n\nbeginaligned\neEmissionsByPlant_gt = (1-Biomass_y- CO2_Capture_Fraction_y) * vFuel_yt * CO2_content + (1-Biomass_y- CO2_Capture_Fraction_Startup_y) * eStartFuel_yt * CO2_content \nhspace1cm forall y in G forall t in T Biomass_y in 01\nendaligned\n\nWhere Biomass_y represents a binary variable (1 or 0) that determines if the generator y uses biomass, and CO2_Capture_Fraction_y represents a fraction for CO2 capture rate.\n\nIn addition to CO2 emissions, for generators with a non-zero CO2 capture rate, we also determine the amount of CO2 being captured and sequestered. The CO2 emissions from generator y at time t, denoted by eEmissionsCaptureByPlant_gt, are determined by total fuel consumption (MMBTU) multiplied by the CO_2 content of the fuel (tCO2/MMBTU), times CO2 capture rate. \n\nbeginaligned\neEmissionsCaptureByPlant_gt = CO2_Capture_Fraction_y * vFuel_yt * CO2_content + CO2_Capture_Fraction_Startup_y * eStartFuel_yt * CO2_content\nhspace1cm forall y in G forall t in T\nendaligned\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#GenX.write_co2-Tuple{AbstractString, Dict, Dict, JuMP.Model}","page":"Core","title":"GenX.write_co2","text":"write_co2(path::AbstractString, inputs::Dict, setup::Dict, EP::Model)\n\nFunction for reporting time-dependent CO2 emissions by zone.\n\n\n\n\n\n","category":"method"},{"location":"Model_Reference/core/#Fuel","page":"Core","title":"Fuel","text":"","category":"section"},{"location":"Model_Reference/core/","page":"Core","title":"Core","text":"Modules = [GenX]\nPages = [\"fuel.jl\"]","category":"page"},{"location":"Model_Reference/core/#GenX.fuel!-Tuple{JuMP.Model, Dict, Dict}","page":"Core","title":"GenX.fuel!","text":"fuel!(EP::Model, inputs::Dict, setup::Dict)\n\nThis function creates expressions to account for total fuel consumption (e.g., coal, natural gas, hydrogen, etc). It also has the capability to model heat rates that are a function of load via a piecewise-linear approximation.\n\n***** Expressions ****** Users have two options to model the fuel consumption as a function of power generation: (1). Use a constant heat rate, regardless of the minimum load or maximum load; and (2). Use the PiecewiseFuelUsage-related parameters to model the fuel consumption via a piecewise-linear approximation of the heat rate curves. By using this option, users can represent the fact that most generators have a decreasing heat rate as a function of load.\n\n(1). Constant heat rate. The fuel consumption for power generation vFuel_yt is determined by power generation (vP_yt) mutiplied by the corresponding heat rate (Heat_Rate_y). The fuel costs for power generation and start fuel for a plant y at time t, denoted by eCFuelOut_yt and eFuelStart, are determined by fuel consumption (vFuel_yt and eStartFuel) multiplied by the fuel costs ($/MMBTU) (2). Piecewise-linear approximation With this formulation, the heat rate of generators becomes a function of load. In reality this relationship takes a nonlinear form, but we model it through a piecewise-linear approximation:\n\nbeginaligned\nvFuel_yt = vP_yt * h_yx + U_gt* f_yx\nhspace1cm forall y in G forall t in T forall x in X\nendaligned\n\nWhere h_yx represents the heat rate slope for generator y in segment x [MMBTU/MWh], f_yx represents the heat rate intercept (MMBTU) for a generator y in segment x [MMBTU], and U_yt represents the commitment status of a generator y at time t. These parameters are optional inputs to the resource .csv files. When Unit commitment is on, if a user provides slope and intercept, the standard heat rate (i.e., HeatRateMMBTUperMWh) will not be used. When unit commitment is off, the model will always use the standard heat rate. The user should determine the slope and intercept parameters based on the CapSize of the plant. For example, when a plant is operating at the full load (i.e., power output equal to the CapSize), the fuel usage determined by the effective segment divided by Cap_Size should be equal to the heat rate at full-load.\n\nSince fuel consumption and fuel costs are postive, the optimization will force the fuel usage to be equal to the highest fuel usage segment for any given value of vP. When the power output is zero, the commitment variable U_gt will bring the intercept to be zero such that the fuel consumption is zero when thermal units are offline.\n\nIn order to run piecewise fuel consumption module, the unit commitment must be turned on (UC = 1 or 2), and users should provide PWFUSlope* and PWFUIntercept* for at least one segment. \n\nTo enable resources to use multiple fuels during both startup and normal operational processes, three additional variables were added: fuel i consumption by plant y at time t (vMulFuel_yit); startup fuel consumption for single-fuel plants (vStartFuel_yt); and startup fuel consumption for multi-fuel plants (vMulStartFuel_yit). By making startup fuel consumption variables, the model can choose the startup fuel to meet the constraints. \n\nFor plants using multiple fuels:\n\nDuring startup, heat input from multiple startup fuels are equal to startup fuel requirements in plant y at time t: StartFuelMMBTUperMW times Capsize.\n\nbeginaligned\nsum_i in mathcalI vMulStartFuels_y i t= CapSize_y times StartFuelMMBTUperMW_y times vSTART_yt\nendaligned\n\nDuring normal operation, the sum of fuel consumptions from multiple fuels dividing by the correspnding heat rates, respectively, is equal to vPower in plant y at time t. \n\nbeginaligned\nsum_i in mathcalI fracvMulFuels_y i t HeatRate_iy = vPower_yt\nendaligned\n\nThere are also constraints on how much heat input each fuel can provide, which are specified by MinCofire and MaxCofire. ```math \\begin{aligned} vMulFuels{y, i, t} >= vPower{y,t} \\times MinCofire{i} \\end{aligned} \\begin{aligned} vMulFuels{y, i, t} <= vPower{y,t} \\times MaxCofire{i} \\end{aligned}\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#How-to-contribute-to-GenX","page":"Developer Docs","title":"How to contribute to GenX","text":"","category":"section"},{"location":"developer_guide/#Introduction","page":"Developer Docs","title":"Introduction","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX is an open-source project, and we welcome contributions from the community. This guide aims to help you get started with GenX and explain how to contribute to the project. In general, the two main ways to contribute to GenX are:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Use of GitHub issues to report bugs and request new features\nUse of GitHub pull requests (PR) to submit code changes","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"tip: Tip\nWe encourage every contributors to read this guide, which contains some guidelines on how to contribute to a collaborative project like GenX.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The following sections describe in more detail how to work with GenX resources and how to add a new resource to GenX.","category":"page"},{"location":"developer_guide/#GenX-resources","page":"Developer Docs","title":"GenX resources","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"In GenX, a resource is defined as an instance of a GenX resource type, a subtype of an AbstractResource. This allows the code to use multiple dispatch and define a common interface (behavior) for all resources in the code. Type hierarchy of GenX resources:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"(Image: Type hierarchy of GenX resources)","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"note: Note\nAll the interface and utility functions available for resources are defined in the resources.jl file. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The set of all the resource types available in GenX are contained in the resource_types Tuple defined at the of the resources.jl file. During the initialization process, GenX reads the input data files and creates a new instance of the corresponding resource type for each row in the file. ","category":"page"},{"location":"developer_guide/#Resource-design-principles","page":"Developer Docs","title":"Resource design principles","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Resources in GenX are constructed from a set of input files (in .csv format, one for each type of resource) located in the resources folder inside the case folder. Each row in one of these files defines a new resource instance, and each column corresponds to an attribute of that resource type. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"warning: Warning\nThe first column of each input data file should be called Resource and contain a unique identifier for each resource.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, in the case below, the files Hydro.csv, Thermal.csv, Vre.csv, and Storage.csv contain the resource data for the hydro, thermal, VRE, and storage resources, respectively. These files are read by GenX during the initialization process and used to create the corresponding resource instances.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"case_folder\n ├── resources\n │ ├── Hydro.csv\n │ ├── Thermal.csv\n │ ├── Vre.csv\n │ └── Storage.csv\n ├── system\n │ └── Generators_variability.csv\n //\n ├── setting\n │ └── genx_settings.yml\n └── Run.jl","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"When loading the file Thermal.csv below, GenX will create three new resources of type Thermal and assign the values of the attributes of each resource from the columns in the input data file:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Thermal.csv\n\n resource │ zone │ existing_cap_mw │ inv_cost_per_mwyr │ heat_rate_mmbtu_per_mwh │\n String │ Int64 │ Float64 │ Float64 │ Float64 │\n────────────────────-┼───────┼─────────────────┼───────────────────┼─────────────────────────│\n NG_combined_cycle_1 │ 1 │ 100.0 │ 239841 │ 7.89 │\n NG_combined_cycle_2 │ 2 │ 200.0 │ 0.0 │ 8.29 │\n Biomass │ 3 │ 200.0 │ 81998 │ 9.9 │","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"These three resources, together with all the other resources in the data files, will be stored in the GenX inputs dictionary with the key RESOURCES.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> gen = inputs[\"RESOURCES\"]\njulia> length(gen) # returns the number of resources in the model\njulia> thermal(gen) # returns the indices of all thermal resources (Vector{Int64})\njulia> gen.Thermal # returns the thermal resources (Vector{Thermal})\njulia> gen.Thermal == gen[thermal(gen)] # returns true","category":"page"},{"location":"developer_guide/#Working-with-GenX-resources","page":"Developer Docs","title":"Working with GenX resources","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"To access the attributes of each resource, you can either use a function interface or the standard . notation. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, let's assume that thermal_gen is the vector of the three Thermal resources created from the input data file Thermal.csv shown above. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"note: Note\nIn the example below, we create the vector thermal_gen manually. However, in practice, this vector is automatically created by GenX when loading the input data file Thermal.csv.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"DocTestSetup = quote\n using GenX: AbstractResource, Thermal, resource_name, existing_cap_mw, inv_cost_per_mwyr, ids_with, ids_with_positive, ids_with_nonneg, ids_with_policy, resource_id, esr, haskey\nend","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> thermal_gen = [Thermal(Dict(:resource => \"NG_combined_cycle_1\", \n :existing_cap_mw => 100.0, \n :inv_cost_per_mwyr => 239841, \n :heat_rate_mmbtu_per_mwh => 7.89,\n :id => 23,\n :max_cap_mw => 100.0,\n :esr_1 => 1,)),\n Thermal(Dict(:resource => \"NG_combined_cycle_2\",\n :existing_cap_mw => 200.0,\n :inv_cost_per_mwyr => 0.0,\n :heat_rate_mmbtu_per_mwh => 8.29,\n :max_cap_mw => 0,\n :id => 24)),\n Thermal(Dict(:resource => \"Biomass\",\n :existing_cap_mw => 200.0,\n :inv_cost_per_mwyr => 81998,\n :heat_rate_mmbtu_per_mwh => 9.9, \n :max_cap_mw => 0,\n :lds => 1,\n :new_build => 1,\n :id => 25))];","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"To access the attributes of the resources in thermal_gen, you can either use the function interfaces defined in resources.jl (recommended), or you can use the standard . notation:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> resource_name(thermal_gen[1])\n\"NG_combined_cycle_1\"\njulia> resource_name.(thermal_gen)\n3-element Vector{String}:\n \"NG_combined_cycle_1\"\n \"NG_combined_cycle_2\"\n \"Biomass\"\njulia> existing_cap_mw(thermal_gen[1])\n100.0\njulia> existing_cap_mw.(thermal_gen)\n3-element Vector{Float64}:\n 100.0\n 200.0\n 200.0\njulia> thermal_gen[1].existing_cap_mw\n100.0","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Moreover, inside the resources.jl file, there is a set of utility functions to work with all the resources and that can be used as building blocks to create more complex functions:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Base.get: Returns the value of the attribute sym of the resource r. If the attribute is not defined for the resource, it returns the default value of that attribute.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> get(thermal_gen[1], :existing_cap_mw, 0)\n100.0\njulia> get(thermal_gen[1], :new_build, 0)\n0","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Base.haskey: Returns true if the resource r has the attribute sym, and false otherwise.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> haskey(thermal_gen[1], :existing_cap_mw)\ntrue\njulia> haskey(thermal_gen[1], :new_build)\nfalse","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Base.findall: Returns the indices of the resources in rs for which the function f returns true.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> findall(r -> isa(r,Thermal), thermal_gen) # returns the indices of the thermal resources in thermal_gen\n3-element Vector{Int64}:\n 23\n 24\n 25\njulia> findall(r -> get(r, :lds, 0) > 0, thermal_gen) # returns the indices of the resources in thermal_gen that have a Long Duration Storage (lds) attribute greater than 0\n1-element Vector{Int64}:\n 25\njulia> findall(r -> get(r, :new_build, 0) == 1, thermal_gen) # returns the indices of the resources in thermal_gen that are buildable (new_build = 1)\n1-element Vector{Int64}:\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with: Returns the indices of the resources in the vector rs for which the function f is different from default.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with(thermal_gen, inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"A similar function works with Symbols and Strings instead of getter functions:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with(thermal_gen, :inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with_policy: Returns the indices of the resources in the vector rs that have a policy with the name name and the tag tag.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with_policy(thermal_gen, esr, tag=1)\n1-element Vector{Int64}:\n 23","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with_positive: Returns the indices of the resources in the vector rs for which the getter function f returns a positive value.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with_positive(thermal_gen, inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23 \n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"A similar function works with Symbols and Strings instead of getter functions:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> ids_with_positive(thermal_gen, :inv_cost_per_mwyr)\n2-element Vector{Int64}:\n 23\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.ids_with_nonneg: Returns the indices of the resources in rs for which the getter function f returns a non-negative value.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Other useful functions available in GenX are:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.resource_id: Returns the id of the resource r.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> resource_id(thermal_gen[1])\n23\njulia> resource_id.(thermal_gen)\n3-element Vector{Int64}:\n 23\n 24\n 25","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX.resource_name: Returns the name of the resource r.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Example: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"julia> resource_name(thermal_gen[1])\n\"NG_combined_cycle_1\"\njulia> resource_name.(thermal_gen)\n3-element Vector{String}:\n \"NG_combined_cycle_1\"\n \"NG_combined_cycle_2\"\n \"Biomass\"","category":"page"},{"location":"developer_guide/#How-to-add-a-new-resource-to-GenX","page":"Developer Docs","title":"How to add a new resource to GenX","text":"","category":"section"},{"location":"developer_guide/#Overview","page":"Developer Docs","title":"Overview","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX is designed to be modular and highly flexible to comply with the rapidly changing electricity landscape. For this reason, adding a new resource to GenX is relatively straightforward. This guide will walk you through the steps to do it.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"tip: Tip\nBefore you start, ensure you have read the section of the documentation about 1.4 Resources input files. This will help you understand the data format that GenX expects for each resource and where to place the input data files. ","category":"page"},{"location":"developer_guide/#Step-1:-Define-the-new-resource-data-type","page":"Developer Docs","title":"Step 1: Define the new resource data type","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The first step to add a new resource to GenX is to create a new GenX resource type. This is done by adding a new element to the resource_types list of symbols defined at the top of the resources.jl file. This list contains the names of all the resource types available in GenX. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, to add a new resource type called new_resource, you would need to add a new Symbol, :NewResource to the resource_types list:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"const resource_types = (:Thermal,\n :Vre,\n :Hydro,\n :Storage,\n :MustRun,\n :FlexDemand,\n :VreStorage,\n :Electrolyzer,\n :NewResource)","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"We encourage you to use CamelCase for the name of the new resource type.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"The lines right after the resource_types list automatically create a new struct (composite type) for the new resource type. More importantly, the new resource type will be defined as a subtype of the GenX AbstractResource type. This is important because it allows the code to use multiple dispach and define a common interface (behavior) for all resources in GenX. For instance, the resource_id() function will return the id of any resource in GenX, regardless of its type (and therefore will automatically work for the newly created new_resource).","category":"page"},{"location":"developer_guide/#Step-2:-Add-the-filename-of-the-new-resource-type-to-GenX","page":"Developer Docs","title":"Step 2: Add the filename of the new resource type to GenX","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"In GenX, the attributes of a resource are automatically defined from the columns of the corresponding input data file (e.g., Thermal.csv file for the Thermal resources, Hydro.csv file for the Hydro resource, etc). The first column of these files should be called Resource and contain a unique identifier for each resource. The rest of the columns in the input data file will be used to define the attributes of the new resource type. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"So, the second step to add a new resource type to GenX is to add the filename of the input data file to GenX. The list of input data files that GenX loads during the initialization process are defined at the top of the load_resource_data.jl file, inside an internal function called _get_resource_info(). This function returns a NamedTuple called resource_info with the name of the input data file and the name of the resource type for each resource that is available in GenX. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"To add the new resource type to GenX, add a new item to resource_info, where the first field is the name of the input data file and the second is the name of the resource type that was created in Step 1. The names in resource_info are only used to make the code more readable and are arbitrary. ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, if you are adding a new resource type called new_resource, you would need to add the following line to the resource_info: new_resource = (filename=\"New_resource.csv\", type=NewResource), as follows: ","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"function _get_resource_info()\n resource_info = (\n hydro = (filename=\"Hydro.csv\", type=Hydro),\n thermal = (filename=\"Thermal.csv\", type=Thermal),\n vre = (filename=\"Vre.csv\", type=Vre),\n storage = (filename=\"Storage.csv\", type=Storage),\n flex_demand = (filename=\"Flex_demand.csv\", type=FlexDemand),\n must_run = (filename=\"Must_run.csv\", type=MustRun),\n electrolyzer = (filename=\"Electrolyzer.csv\", type=Electrolyzer),\n vre_stor = (filename=\"Vre_stor.csv\", type=VreStorage)\n new_resource = (filename=\"New_resource.csv\", type=NewResource)\n )\n return resource_info\nend","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"With this simple edit, whenever the file New_resource.csv is found in the input data folder, GenX will automatically perform the following steps:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Load the new resource input file,\nCreate a new instance of the NewResource type for each row in the input data file,\nDefine the attributes of each NewResource from the columns in the input data file,\nPopulate the attributes of each NewResource with the values read from the input data file.\nAdd the new resources to the vector of resources in the model.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"For example, if the input data file New_resource.csv contains the following data:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"New_resource.csv\n\n Resource │ Zone | Exisiting_capacity | attribute_1 | attribute_2\n String │ Int64 | Float64 | Float64 | Float64\n──────────┼───────┼────────────────────┼─────────────┼────────────\n new_res1 │ 1 │ 100.0 │ 6.2 │ 0.4\n new_res2 │ 1 │ 200.0 │ 0.1 │ 4.0\n new_res3 │ 2 │ 300.0 │ 2.0 │ 0.1","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"GenX will create three new resources of type NewResource with the following attributes:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"resource: String with the name of the resource (e.g., new_res1, new_res2, new_res3)\nzone: Int64 with the zone of the resource (e.g., 1, 1, 2)\nexisting_capacity: Float64 with the existing capacity of the resource (e.g., 100.0, 200.0, 300.0)\nattribute_1: Float64 with the value of attribute_1 (e.g., 6.2, 0.1, 2.0)\nattribute_2: Float64 with the value of attribute_2 (e.g., 0.4, 4.0, 0.1)","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"See Step 3 for more details on how to work with the new resource type.","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"warning: Warning\nEach resource type must contain a Resource attribute. This attribute should be String that uniquely identifies the resource. ","category":"page"},{"location":"developer_guide/#Step-3:-Work-with-the-new-resource-type","page":"Developer Docs","title":"Step 3: Work with the new resource type","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Once the new resource type has been defined and added to GenX, you can work with it as you would with any other resource type. To improve the robustness and readability of the code, we recommend that you define getter functions for the new attributes of the new resource type (e.g., a function zone(r) = r.zone to get the zone of the resource r). These functions can be defined in the resources.jl file. However, this is not strictly necessary, and you can access the attributes of the new resource type directly using the standard . notation:","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"tip: Tip\nTo simplify the creation of getter functions for the new resource type, you can use the @interface macro available in GenX. This macro automatically creates a new function with the same name as the attribute and which returns the value of the attribute. For example, if you want to create a getter function for the attribute_1 of the NewResource type, these two ways are equivalent:julia> default_attribute_1 = 0.0 # default value for attribute_1\njulia> attribute_1(res::NewResource) = get(res, :attribute_1, default_attribute_1)\nattribute_1 (generic function with 1 method)\njulia> @interface(attribute_1, 0.0, NewResource)\nattribute_1 (generic function with 1 method)And then:julia> attribute_1(new_res1)\n6.2\njulia> new_res1.attribute_1\n6.2","category":"page"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"DocTestSetup = nothing","category":"page"},{"location":"developer_guide/#Utility-functions-to-work-with-JuMP-expressions-in-GenX","page":"Developer Docs","title":"Utility functions to work with JuMP expressions in GenX","text":"","category":"section"},{"location":"developer_guide/","page":"Developer Docs","title":"Developer Docs","text":"Modules = [GenX]\nPages = [\"model/expression_manipulation.jl\"]","category":"page"},{"location":"developer_guide/#GenX.add_similar_to_expression!-Union{Tuple{dim2}, Tuple{dim1}, Tuple{V}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dim1}, AbstractArray{V, dim2}}} where {C, T, V, dim1, dim2}","page":"Developer Docs","title":"GenX.add_similar_to_expression!","text":"add_similar_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dim1}, expr2::AbstractArray{V, dim2}) where {C,T,V,dim1,dim2}\n\nAdd an array of some type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr). However, the accessed parts of both arrays must have the same dimensions.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.add_term_to_expression!-Union{Tuple{dims}, Tuple{V}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dims}, V}} where {C, T, V, dims}","page":"Developer Docs","title":"GenX.add_term_to_expression!","text":"add_term_to_expression!(expr1::AbstractArray{GenericAffExpr{C,T}, dims}, expr2::V) where {C,T,V,dims}\n\nAdd an entry of type V to an array of expressions, in-place. This will work on JuMP DenseContainers which do not have linear indexing from 1:length(arr).\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.check_addable_to_expr-Tuple{DataType, DataType}","page":"Developer Docs","title":"GenX.check_addable_to_expr","text":"check_addable_to_expr(C::DataType, T::DataType)\n\nCheck that two datatype can be added using addtoexpression!(). Raises an error if not.\n\nThis needs some work to make it more flexible. Right now it's challenging to use with GenericAffExpr{C,T} as the method only works on the constituent types making up the GenericAffExpr, not the resulting expression type. Also, the default MethodError from addtoexpression! is sometime more informative than the error message here.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.check_sizes_match-Union{Tuple{dim2}, Tuple{dim1}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{C, dim1}, AbstractArray{T, dim2}}} where {C, T, dim1, dim2}","page":"Developer Docs","title":"GenX.check_sizes_match","text":"check_sizes_match(expr1::AbstractArray{C, dim1}, expr2::AbstractArray{T, dim2}) where {C,T,dim1, dim2}\n\nCheck that two arrays have the same dimensions. If not, return an error message which includes the dimensions of both arrays.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.create_empty_expression!-Union{Tuple{N}, Tuple{JuMP.Model, Symbol, Tuple{Vararg{Int64, N}}}} where N","page":"Developer Docs","title":"GenX.create_empty_expression!","text":"create_empty_expression!(EP::Model, exprname::Symbol, dims::NTuple{N, Int64}) where N\n\nCreate an dense array filled with zeros which can be altered later. Other approaches to creating zero-filled arrays will often return an array of floats, not expressions. This can lead to errors later if a method can only operate on expressions.\n\nWe don't currently have a method to do this with non-contiguous indexing.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.fill_with_const!-Union{Tuple{dims}, Tuple{T}, Tuple{C}, Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dims}, Real}} where {C, T, dims}","page":"Developer Docs","title":"GenX.fill_with_const!","text":"fill_with_const!(arr::AbstractArray{GenericAffExpr{C,T}, dims}, con::Real) where {C,T,dims}\n\nFill an array of expressions with the specified constant, in-place.\n\nIn the future we could expand this to non AffExpr, using GenericAffExpr e.g. if we wanted to use Float32 instead of Float64\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.fill_with_zeros!-Union{Tuple{AbstractArray{JuMP.GenericAffExpr{C, T}, dims}}, Tuple{dims}, Tuple{T}, Tuple{C}} where {C, T, dims}","page":"Developer Docs","title":"GenX.fill_with_zeros!","text":"fill_with_zeros!(arr::AbstractArray{GenericAffExpr{C,T}, dims}) where {C,T,dims}\n\nFill an array of expressions with zeros in-place.\n\n\n\n\n\n","category":"method"},{"location":"developer_guide/#GenX.sum_expression-Union{Tuple{AbstractArray{C, dims}}, Tuple{dims}, Tuple{C}} where {C, dims}","page":"Developer Docs","title":"GenX.sum_expression","text":"sum_expression(expr::AbstractArray{C, dims}) where {C,dims} :: C\n\nSum an array of expressions into a single expression and return the result. We're using errors from addtoexpression!() to check that the types are compatible.\n\n\n\n\n\n","category":"method"}] } diff --git a/previews/PR655/third_party_genx/index.html b/previews/PR655/third_party_genx/index.html index 9fdf3b96db..5b04c13040 100644 --- a/previews/PR655/third_party_genx/index.html +++ b/previews/PR655/third_party_genx/index.html @@ -1,2 +1,2 @@ -Third Party Extensions · GenX

pygenx: Python interface for GenX

Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation.

Simple GenX Case Runner: For automated sequential batch run for GenX

It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner

Bug and feature requests and contact info

If you would like to report a bug in the code or request a feature, please use our Issue Tracker. If you're unsure or have questions on how to use GenX that are not addressed by the above documentation, please reach out to Sambuddha Chakrabarti (sc87@princeton.edu), Luca Bonaldo (lucabonaldo@princeton.edu), Jesse Jenkins (jdj2@princeton.edu) or Dharik Mallapragada (dharik@mit.edu).

+Third Party Extensions · GenX

pygenx: Python interface for GenX

Python users can now run GenX from a thin-python-wrapper interface, developed by Daniel Olsen. This tool is called pygenx and can be cloned from the github page: pygenx. It needs installation of Julia 1.3 and a clone of GenX repo along with your python installation.

Simple GenX Case Runner: For automated sequential batch run for GenX

It is now possible to run a list of GenX cases as separate batch jobs. Alternatively, they can also be run locally in sequence, as one job. It has been developed by Jacob Schwartz. This tool is called SimpleGenXCaseRunner and can be cloned from the github page: SimpleGenXCaseRunner

Bug and feature requests and contact info

If you would like to report a bug in the code or request a feature, please use our Issue Tracker. If you're unsure or have questions on how to use GenX that are not addressed by the above documentation, please reach out to Sambuddha Chakrabarti (sc87@princeton.edu), Luca Bonaldo (lucabonaldo@princeton.edu), Jesse Jenkins (jdj2@princeton.edu) or Dharik Mallapragada (dharik@mit.edu).