Ejemplo n.º 1
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """

    :param m:
    :param d:
    :return:
    """
    # First figure out which projects we need to track for PRM contribution
    m.PRM_PROJECTS = Set(within=m.PROJECTS)
    m.prm_zone = Param(m.PRM_PROJECTS, within=m.PRM_ZONES)
    m.prm_type = Param(m.PRM_PROJECTS,
                       within=[
                           "energy_only_allowed", "fully_deliverable",
                           "fully_deliverable_energy_limited"
                       ])

    m.PRM_PROJECTS_BY_PRM_ZONE = Set(
        m.PRM_ZONES,
        within=m.PRM_PROJECTS,
        initialize=lambda mod, prm_z: subset_init_by_param_value(
            mod, "PRM_PROJECTS", "prm_zone", prm_z))

    # Get operational carbon cap projects - timepoints combinations
    m.PRM_PRJ_OPR_PRDS = Set(
        within=m.PRJ_OPR_PRDS,
        initialize=lambda mod: [(prj, p) for (prj, p) in mod.PRJ_OPR_PRDS
                                if prj in mod.PRM_PROJECTS])
Ejemplo n.º 2
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_ALWAYS_ON`                                                 |
    |                                                                         |
    | The set of generators of the :code:`gen_always_on` operational type.    |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_ALWAYS_ON_OPR_TMPS`                                        |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_always_on`        |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_ALWAYS_ON_LINKED_TMPS`                                     |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_always_on`        |
    | operational type and their linked timepoints.                           |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_always_on_unit_size_mw`                                    |
    | | *Defined over*: :code:`GEN_ALWAYS_ON`                                 |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The MW size of a unit in this project (projects of the                  |
    | :code:`gen_always_on` type can represent a fleet of similar units).     |
    +-------------------------------------------------------------------------+
    | | :code:`gen_always_on_min_stable_level_fraction`                       |
    | | *Defined over*: :code:`GEN_ALWAYS_ON`                                 |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The minimum stable level of this project as a fraction of its capacity. |
    | This can also be interpreted as the minimum stable level of a unit      |
    | within this project (as the project itself can represent multiple       |
    | units with similar characteristics.                                     |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Optional Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_always_on_ramp_up_when_on_rate`                            |
    | | *Defined over*: :code:`GEN_ALWAYS_ON`                                 |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's upward ramp rate limit during operations, defined as a    |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+
    | | :code:`gen_always_on_ramp_down_when_on_rate`                          |
    | | *Defined over*: :code:`GEN_ALWAYS_ON`                                 |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's downward ramp rate limit during operations, defined as a  |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Linked Input Params                                                     |
    +=========================================================================+
    | | :code:`gen_always_on_linked_power`                                    |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_LINKED_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's power provision in the linked timepoints.                 |
    +-------------------------------------------------------------------------+
    | | :code:`gen_always_on_linked_upwards_reserves`                         |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_LINKED_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's upward reserve provision in the linked timepoints.        |
    +-------------------------------------------------------------------------+
    | | :code:`gen_always_on_linked_downwards_reserves`                       |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_LINKED_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's downward reserve provision in the linked timepoints.      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`GenAlwaysOn_Provide_Power_MW`                                  |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_OPR_TMPS`                        |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Power provision in MW from this project in each timepoint in which the  |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | Power                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenAlwaysOn_Max_Power_Constraint`                              |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_OPR_TMPS`                        |
    |                                                                         |
    | Limits the power plus upward reserves to the available capacity.        |
    +-------------------------------------------------------------------------+
    | | :code:`GenAlwaysOn_Min_Power_Constraint`                              |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_OPR_TMPS`                        |
    |                                                                         |
    | Power provision minus downward reserves should exceed the minimum       |
    | stable level for the project.                                           |
    +-------------------------------------------------------------------------+
    | Ramps                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenAlwaysOn_Ramp_Up_Constraint`                                |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_OPR_TMPS`                        |
    |                                                                         |
    | Limits the allowed project upward ramp based on the                     |
    | :code:`gen_always_on_ramp_up_when_on_rate`.                             |
    +-------------------------------------------------------------------------+
    | | :code:`GenAlwaysOn_Ramp_Down_Constraint`                              |
    | | *Defined over*: :code:`GEN_ALWAYS_ON_OPR_TMPS`                        |
    |                                                                         |
    | Limits the allowed project downward ramp based on the                   |
    | :code:`gen_always_on_ramp_down_when_on_rate`.                           |
    +-------------------------------------------------------------------------+


    """

    # Sets
    ###########################################################################
    m.GEN_ALWAYS_ON = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "gen_always_on"))

    m.GEN_ALWAYS_ON_OPR_TMPS = Set(dimen=2,
                                   within=m.PRJ_OPR_TMPS,
                                   initialize=lambda mod: list(
                                       set((g, tmp)
                                           for (g, tmp) in mod.PRJ_OPR_TMPS
                                           if g in mod.GEN_ALWAYS_ON)))

    m.GEN_ALWAYS_ON_LINKED_TMPS = Set(dimen=2)

    # Required Params
    ###########################################################################

    m.gen_always_on_unit_size_mw = Param(m.GEN_ALWAYS_ON,
                                         within=NonNegativeReals)

    m.gen_always_on_min_stable_level_fraction = Param(m.GEN_ALWAYS_ON,
                                                      within=PercentFraction)

    # Optional Params
    ###########################################################################

    m.gen_always_on_ramp_up_when_on_rate = Param(m.GEN_ALWAYS_ON,
                                                 within=PercentFraction,
                                                 default=1)

    m.gen_always_on_ramp_down_when_on_rate = Param(m.GEN_ALWAYS_ON,
                                                   within=PercentFraction,
                                                   default=1)

    # Linked Params
    ###########################################################################

    m.gen_always_on_linked_power = Param(m.GEN_ALWAYS_ON_LINKED_TMPS,
                                         within=NonNegativeReals)

    m.gen_always_on_linked_upwards_reserves = Param(
        m.GEN_ALWAYS_ON_LINKED_TMPS, within=NonNegativeReals)

    m.gen_always_on_linked_downwards_reserves = Param(
        m.GEN_ALWAYS_ON_LINKED_TMPS, within=NonNegativeReals)

    # Variables
    ###########################################################################

    m.GenAlwaysOn_Provide_Power_MW = Var(m.GEN_ALWAYS_ON_OPR_TMPS,
                                         within=NonNegativeReals)

    # Expressions
    ###########################################################################
    # TODO: the reserve rules are the same in all modules, so should be
    #  consolidated
    def upwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, headroom_variables)[g])

    m.GenAlwaysOn_Upwards_Reserves_MW = Expression(m.GEN_ALWAYS_ON_OPR_TMPS,
                                                   rule=upwards_reserve_rule)

    def downwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, footroom_variables)[g])

    m.GenAlwaysOn_Downwards_Reserves_MW = Expression(
        m.GEN_ALWAYS_ON_OPR_TMPS, rule=downwards_reserve_rule)

    # Constraints
    ###########################################################################

    m.GenAlwaysOn_Min_Power_Constraint = Constraint(m.GEN_ALWAYS_ON_OPR_TMPS,
                                                    rule=min_power_rule)

    m.GenAlwaysOn_Max_Power_Constraint = Constraint(m.GEN_ALWAYS_ON_OPR_TMPS,
                                                    rule=max_power_rule)

    m.GenAlwaysOn_Ramp_Up_Constraint = Constraint(m.GEN_ALWAYS_ON_OPR_TMPS,
                                                  rule=ramp_up_rule)

    m.GenAlwaysOn_Ramp_Down_Constraint = Constraint(m.GEN_ALWAYS_ON_OPR_TMPS,
                                                    rule=ramp_down_rule)
Ejemplo n.º 3
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_SIMPLE`                                                    |
    |                                                                         |
    | The set of generators of the :code:`gen_simple` operational type.       |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_SIMPLE_OPR_TMPS`                                           |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_simple`           |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_SIMPLE_LINKED_TMPS`                                        |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_simple`           |
    | operational type and their linked timepoints.                           |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Optional Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_simple_ramp_up_when_on_rate`                               |
    | | *Defined over*: :code:`GEN_SIMPLE`                                    |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's upward ramp rate limit during operations, defined as a    |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+
    | | :code:`gen_simple_ramp_down_when_on_rate`                             |
    | | *Defined over*: :code:`GEN_SIMPLE`                                    |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's downward ramp rate limit during operations, defined as a  |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Linked Input Params                                                     |
    +=========================================================================+
    | | :code:`gen_simple_linked_power`                                       |
    | | *Defined over*: :code:`GEN_SIMPLE_LINKED_TMPS`                        |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's power provision in the linked timepoints.                 |
    +-------------------------------------------------------------------------+
    | | :code:`gen_simple_linked_upwards_reserves`                            |
    | | *Defined over*: :code:`GEN_SIMPLE_LINKED_TMPS`                        |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's upward reserve provision in the linked timepoints.        |
    +-------------------------------------------------------------------------+
    | | :code:`gen_simple_linked_downwards_reserves`                          |
    | | *Defined over*: :code:`GEN_SIMPLE_LINKED_TMPS`                        |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's downward reserve provision in the linked timepoints.      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`GenSimple_Provide_Power_MW`                                    |
    | | *Defined over*: :code:`GEN_SIMPLE_OPR_TMPS`                           |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Power provision in MW from this project in each timepoint in which the  |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | Power                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenSimple_Max_Power_Constraint`                                |
    | | *Defined over*: :code:`GEN_SIMPLE_OPR_TMPS`                           |
    |                                                                         |
    | Limits the power plus upward reserves to the available capacity.        |
    +-------------------------------------------------------------------------+
    | | :code:`GenSimple_Min_Power_Constraint`                                |
    | | *Defined over*: :code:`GEN_SIMPLE_OPR_TMPS`                           |
    |                                                                         |
    | Power provision minus downward reserves should exceed the minimum       |
    | stable level for the project.                                           |
    +-------------------------------------------------------------------------+
    | Ramps                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenSimple_Ramp_Up_Constraint`                                  |
    | | *Defined over*: :code:`GEN_SIMPLE_OPR_TMPS`                           |
    |                                                                         |
    | Limits the allowed project upward ramp based on the                     |
    | :code:`gen_simple_ramp_up_when_on_rate`.                                |
    +-------------------------------------------------------------------------+
    | | :code:`GenSimple_Ramp_Down_Constraint`                                |
    | | *Defined over*: :code:`GEN_SIMPLE_OPR_TMPS`                           |
    |                                                                         |
    | Limits the allowed project downward ramp based on the                   |
    | :code:`gen_simple_ramp_down_when_on_rate`.                              |
    +-------------------------------------------------------------------------+

    """

    # Sets
    ###########################################################################

    m.GEN_SIMPLE = Set(within=m.PROJECTS,
                       initialize=lambda mod: subset_init_by_param_value(
                           mod, "PROJECTS", "operational_type", "gen_simple"))

    m.GEN_SIMPLE_OPR_TMPS = Set(dimen=2,
                                within=m.PRJ_OPR_TMPS,
                                initialize=lambda mod: set(
                                    (g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS
                                    if g in mod.GEN_SIMPLE))

    m.GEN_SIMPLE_LINKED_TMPS = Set(dimen=2)

    # Optional Params
    ###########################################################################

    m.gen_simple_ramp_up_when_on_rate = Param(m.GEN_SIMPLE,
                                              within=PercentFraction,
                                              default=1)
    m.gen_simple_ramp_down_when_on_rate = Param(m.GEN_SIMPLE,
                                                within=PercentFraction,
                                                default=1)

    # Linked Params
    ###########################################################################

    m.gen_simple_linked_power = Param(m.GEN_SIMPLE_LINKED_TMPS,
                                      within=NonNegativeReals)

    m.gen_simple_linked_upwards_reserves = Param(m.GEN_SIMPLE_LINKED_TMPS,
                                                 within=NonNegativeReals)

    m.gen_simple_linked_downwards_reserves = Param(m.GEN_SIMPLE_LINKED_TMPS,
                                                   within=NonNegativeReals)

    # Variables
    ###########################################################################

    m.GenSimple_Provide_Power_MW = Var(m.GEN_SIMPLE_OPR_TMPS,
                                       within=NonNegativeReals)

    # Expressions
    ###########################################################################

    def upwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, headroom_variables)[g])

    m.GenSimple_Upwards_Reserves_MW = Expression(m.GEN_SIMPLE_OPR_TMPS,
                                                 rule=upwards_reserve_rule)

    def downwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, footroom_variables)[g])

    m.GenSimple_Downwards_Reserves_MW = Expression(m.GEN_SIMPLE_OPR_TMPS,
                                                   rule=downwards_reserve_rule)

    # Constraints
    ###########################################################################

    m.GenSimple_Max_Power_Constraint = Constraint(m.GEN_SIMPLE_OPR_TMPS,
                                                  rule=max_power_rule)

    m.GenSimple_Min_Power_Constraint = Constraint(m.GEN_SIMPLE_OPR_TMPS,
                                                  rule=min_power_rule)

    m.GenSimple_Ramp_Up_Constraint = Constraint(m.GEN_SIMPLE_OPR_TMPS,
                                                rule=ramp_up_rule)

    m.GenSimple_Ramp_Down_Constraint = Constraint(m.GEN_SIMPLE_OPR_TMPS,
                                                  rule=ramp_down_rule)
Ejemplo n.º 4
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_HYDRO`                                                     |
    |                                                                         |
    | The set of generators of the :code:`gen_hydro` operational type.        |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_HYDRO_OPR_HRZS`                                            |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_hydro`            |
    | operational type and their operational horizons.                        |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_HYDRO_OPR_TMPS`                                            |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_hydro`            |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_HYDRO_LINKED_TMPS`                                         |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_hydro`            |
    | operational type and their linked timepoints.                           |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_hydro_max_power_fraction`                                  |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS`                            |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The project's maximum power output in each operational horizon as a     |
    | fraction of its available capacity.                                     |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_min_power_fraction`                                  |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS`                            |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The project's minimum power output in each operational horizon as a     |
    | fraction of its available capacity.                                     |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_average_power_fraction`                              |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS`                            |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The project's avarage power output in each operational horizon as a     |
    | fraction of its available capacity. This can be interpreted as the      |
    | project's average capacity factor or plant load factor.                 |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Optional Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_hydro_ramp_up_when_on_rate`                                |
    | | *Defined over*: :code:`GEN_HYDRO`                                     |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's upward ramp rate limit during operations, defined as a    |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_ramp_down_when_on_rate`                              |
    | | *Defined over*: :code:`GEN_HYDRO`                                     |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's downward ramp rate limit during operations, defined as a  |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Linked Input Params                                                     |
    +=========================================================================+
    | | :code:`gen_hydro_linked_power`                                        |
    | | *Defined over*: :code:`GEN_HYDRO_LINKED_TMPS`                         |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's power provision in the linked timepoints.                 |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_linked_curtailment`                                  |
    | | *Defined over*: :code:`GEN_HYDRO_LINKED_TMPS`                         |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's curtailment in the linked timepoints.                     |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_linked_upwards_reserves`                             |
    | | *Defined over*: :code:`GEN_HYDRO_LINKED_TMPS`                         |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's upward reserve provision in the linked timepoints.        |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_linked_downwards_reserves`                           |
    | | *Defined over*: :code:`GEN_HYDRO_LINKED_TMPS`                         |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's downward reserve provision in the linked timepoints.      |
    +-------------------------------------------------------------------------+
    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`GenHydro_Provide_Power_MW`                                     |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_TMPS`                            |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Power provision in MW from this project in each timepoint in which the  |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydro_Curtail_MW`                                           |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_TMPS`                            |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Curtailment in MW from this project in each timepoint in which the      |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | Power                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydro_Max_Power_Constraint`                                 |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS`                            |
    |                                                                         |
    | Limits the power plus upward reserves based on the                      |
    | :code:`gen_hydro_max_power_fraction` and the available capacity.        |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydro_Min_Power_Constraint`                                 |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS`                            |
    |                                                                         |
    | Power provision minus downward reserves should exceed a certain level   |
    | based on the :code:`gen_hydro_min_power_fraction` and the available     |
    | capacity.                                                               |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydro_Energy_Budget_Constraint`                             |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_HRZS`                            |
    |                                                                         |
    | The project's average capacity factor in each operational horizon,      |
    | including curtailment, should match the specified                       |
    | :code:`gen_hydro_average_power_fraction`.                               |
    +-------------------------------------------------------------------------+
    | Ramps                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydro_Ramp_Up_Constraint`                                   |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_TMPS`                            |
    |                                                                         |
    | Limits the allowed project upward ramp based on the                     |
    | :code:`gen_hydro_ramp_up_when_on_rate`.                                 |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydro_Ramp_Down_Constraint`                                 |
    | | *Defined over*: :code:`GEN_HYDRO_OPR_TMPS`                            |
    |                                                                         |
    | Limits the allowed project downward ramp based on the                   |
    | :code:`gen_hydro_ramp_down_when_on_rate`.                               |
    +-------------------------------------------------------------------------+

    """
    # Sets
    ###########################################################################

    m.GEN_HYDRO = Set(within=m.PROJECTS,
                      initialize=lambda mod: subset_init_by_param_value(
                          mod, "PROJECTS", "operational_type", "gen_hydro"))

    m.GEN_HYDRO_OPR_HRZS = Set(dimen=2)

    m.GEN_HYDRO_OPR_TMPS = Set(dimen=2,
                               within=m.PRJ_OPR_TMPS,
                               initialize=lambda mod: set(
                                   (g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS
                                   if g in mod.GEN_HYDRO))

    m.GEN_HYDRO_LINKED_TMPS = Set(dimen=2)

    # Required Params
    ###########################################################################

    m.gen_hydro_max_power_fraction = Param(m.GEN_HYDRO_OPR_HRZS,
                                           within=PercentFraction)

    m.gen_hydro_min_power_fraction = Param(m.GEN_HYDRO_OPR_HRZS,
                                           within=PercentFraction)

    m.gen_hydro_average_power_fraction = Param(m.GEN_HYDRO_OPR_HRZS,
                                               within=PercentFraction)

    # Optional Params
    ###########################################################################

    m.gen_hydro_ramp_up_when_on_rate = Param(m.GEN_HYDRO,
                                             within=PercentFraction,
                                             default=1)

    m.gen_hydro_ramp_down_when_on_rate = Param(m.GEN_HYDRO,
                                               within=PercentFraction,
                                               default=1)

    # Linked Params
    ###########################################################################

    m.gen_hydro_linked_power = Param(m.GEN_HYDRO_LINKED_TMPS,
                                     within=NonNegativeReals)

    m.gen_hydro_linked_curtailment = Param(m.GEN_HYDRO_LINKED_TMPS,
                                           within=NonNegativeReals)

    m.gen_hydro_linked_upwards_reserves = Param(m.GEN_HYDRO_LINKED_TMPS,
                                                within=NonNegativeReals)

    m.gen_hydro_linked_downwards_reserves = Param(m.GEN_HYDRO_LINKED_TMPS,
                                                  within=NonNegativeReals)

    # Variables
    ###########################################################################

    m.GenHydro_Provide_Power_MW = Var(m.GEN_HYDRO_OPR_TMPS,
                                      within=NonNegativeReals)

    m.GenHydro_Curtail_MW = Var(m.GEN_HYDRO_OPR_TMPS, within=NonNegativeReals)

    # Expressions
    ###########################################################################

    def upwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, headroom_variables)[g])

    m.GenHydro_Upwards_Reserves_MW = Expression(m.GEN_HYDRO_OPR_TMPS,
                                                rule=upwards_reserve_rule)

    def downwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, footroom_variables)[g])

    m.GenHydro_Downwards_Reserves_MW = Expression(m.GEN_HYDRO_OPR_TMPS,
                                                  rule=downwards_reserve_rule)

    # Constraints
    ###########################################################################

    m.GenHydro_Max_Power_Constraint = Constraint(m.GEN_HYDRO_OPR_TMPS,
                                                 rule=max_power_rule)

    m.GenHydro_Min_Power_Constraint = Constraint(m.GEN_HYDRO_OPR_TMPS,
                                                 rule=min_power_rule)

    m.GenHydro_Energy_Budget_Constraint = Constraint(m.GEN_HYDRO_OPR_HRZS,
                                                     rule=energy_budget_rule)

    m.GenHydro_Ramp_Up_Constraint = Constraint(m.GEN_HYDRO_OPR_TMPS,
                                               rule=ramp_up_rule)

    m.GenHydro_Ramp_Down_Constraint = Constraint(m.GEN_HYDRO_OPR_TMPS,
                                                 rule=ramp_down_rule)
Ejemplo n.º 5
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_VAR_STOR_HYB`                                              |
    |                                                                         |
    | The set of generators of the :code:`gen_var_stor_hyb` operational type. |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                                     |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_var_stor_hyb`     |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_var_stor_hyb_cap_factor`                                   |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB`                              |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's power output in each operational timepoint as a fraction  |
    | of its available capacity (i.e. the capacity factor).                   |
    +-------------------------------------------------------------------------+
    | | :code:`gen_var_stor_hyb_charging_efficiency`                          |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB`                              |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The project's storage component charging efficiency (1 = 100%           |
    | efficient).                                                             |
    +-------------------------------------------------------------------------+
    | | :code:`gen_var_stor_hyb_discharging_efficiency`                       |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB`                              |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The project's storage component discharging efficiency (1 = 100%        |
    | efficient).                                                             |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`GenVarStorHyb_Provide_Power_MW`                                |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Power provision in MW from this project in each timepoint in which the  |
    | project is operational (capacity exists and the project is available).  |
    | This can come either directly from the variable resource via the        |
    | the generator component or from the storage component.                  |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Charge_MW`                                       |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Charging power in MW from this project in each timepoint in which the   |
    | project is operational (capacity exists and the project is available).  |
    | This operational type can only charge from the variable resource, not   |
    | from the grid.                                                          |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Discharge_MW`                                    |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Discharging power in MW from this project in each timepoint in which the|
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Starting_Energy_in_Storage_MWh`                  |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The state of charge of the project's storage component  at the start of |
    | each timepoint, in MWh of energy stored.                                |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Expressions                                                             |
    +=========================================================================+
    | | :code:`GenVarStorHyb_Available_Power_MW`                              |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | The available power from the variable resource.                         |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Scheduled_Curtailment_MW`                        |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | The available power minus what was actually provided (in MW).           |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Subtimepoint_Curtailment_MW`                     |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Curtailment resulting from provision of downward reserves.              |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Total_Curtailment_MW`                            |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Scheduled curtailment (in MW) plus an upward adjustment for additional  |
    | curtailment when providing downward reserves, and a downward adjustment |
    | adjustment for a reduction in curtailment when providing upward         |
    | reserves, to account for sub-hourly dispatch when providing reserves.   |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Subtimepoint_Energy_Delivered_MW`                |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Delivered energy resulting from provision of upward reserves.           |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | | :code:`GenVarStorHyb_Max_Power_Constraint`                            |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | The project's power and upward reserves cannot exceed the available     |
    | capacity.                                                               |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Max_Available_Power_Constraint`                  |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Limits the power plus upward reserves in each timepoint based on the    |
    | product of :code:`gen_var_stor_hyb_cap_factor` and the available        |
    | capacity (available power) plus the net power from storage.             |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Min_Power_Constraint`                            |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Power provision minus downward reserves should be greater than or equal |
    | to zero. We are assuming that the hybrid storage cannot charge from the |
    | grid (so power provision cannot go negative).                           |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Max_Charge_Constraint`                           |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Storage charging power can't exceed available storage component         |
    | capacity.                                                               |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Max_Discharge_Constraint`                        |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | Storage discharging power can't exceed available storage component      |
    | capacity.                                                               |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Energy_Tracking_Constraint`                      |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | The energy stored in each timepoint is equal to the energy stored in    |
    | the previous timepoint minus any discharged power (adjusted for         |
    | discharging efficiency and timepoint duration) plus any charged power   |
    | (adjusted for charging efficiency and timepoint duration).              |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Max_Energy_in_Storage_Constraint`                |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | The amount of energy stored in each operational timepoint cannot exceed |
    | the available energy capacity.                                          |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarStorHyb_Max_Headroom_Energy_Constraint`                  |
    | | *Defined over*: :code:`GEN_VAR_STOR_HYB_OPR_TMPS`                     |
    |                                                                         |
    | The project cannot provide more upward reserves (reserve provision      |
    | times sustained duration required) than the available energy (from      |
    | resource and from storage) after accounting for power provision. Said   |
    | differently, we must have enough energy available to remain at the new  |
    | set point (for the full duration of the timepoint).                     |
    +-------------------------------------------------------------------------+

    """

    # Sets
    ###########################################################################
    m.GEN_VAR_STOR_HYB = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "gen_var_stor_hyb"
        ),
    )

    m.GEN_VAR_STOR_HYB_OPR_TMPS = Set(
        dimen=2,
        within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: list(
            set(
                (prj, tmp)
                for (prj, tmp) in mod.PRJ_OPR_TMPS
                if prj in mod.GEN_VAR_STOR_HYB
            )
        ),
    )

    # Required Params
    ###########################################################################

    m.gen_var_stor_hyb_cap_factor = Param(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, within=NonNegativeReals
    )

    m.gen_var_stor_hyb_charging_efficiency = Param(
        m.GEN_VAR_STOR_HYB, within=PercentFraction
    )

    m.gen_var_stor_hyb_discharging_efficiency = Param(
        m.GEN_VAR_STOR_HYB, within=PercentFraction
    )

    # Variables
    ###########################################################################

    m.GenVarStorHyb_Provide_Power_MW = Var(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, within=NonNegativeReals
    )

    m.GenVarStorHyb_Charge_MW = Var(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, within=NonNegativeReals
    )

    m.GenVarStorHyb_Discharge_MW = Var(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, within=NonNegativeReals
    )

    m.GenVarStorHyb_Starting_Energy_in_Storage_MWh = Var(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, within=NonNegativeReals
    )

    # Expressions
    ###########################################################################

    def available_power_rule(mod, prj, tmp):
        """
        The amount of power from the variable resource generation component
        (e.g. solar field) available in every timepoint.
        """
        return (
            mod.Hyb_Gen_Capacity_MW[prj, mod.period[tmp]]
            * mod.Availability_Derate[prj, tmp]
            * mod.gen_var_stor_hyb_cap_factor[prj, tmp]
        )

    m.GenVarStorHyb_Available_Power_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=available_power_rule
    )

    def upwards_reserve_rule(mod, prj, tmp):
        """
        Gather all headroom variables, and de-rate the total reserves offered
        to account for the fact that gen_var_stor_hyb output is uncertain.
        """
        return sum(
            getattr(mod, c)[prj, tmp]
            / getattr(mod, getattr(d, reserve_variable_derate_params)[c])[prj]
            for c in getattr(d, headroom_variables)[prj]
        )

    m.GenVarStorHyb_Upward_Reserves_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=upwards_reserve_rule
    )

    def downwards_reserve_rule(mod, prj, tmp):
        """
        Gather all footroom variables, and de-rate the total reserves offered
        to account for the fact that gen_var_stor_hyb output is uncertain.
        """
        return sum(
            getattr(mod, c)[prj, tmp]
            / getattr(mod, getattr(d, reserve_variable_derate_params)[c])[prj]
            for c in getattr(d, footroom_variables)[prj]
        )

    m.GenVarStorHyb_Downward_Reserves_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=downwards_reserve_rule
    )

    def subtimepoint_curtailment_expression_rule(mod, prj, tmp):
        """
        Sub-hourly curtailment from providing downward reserves.
        """
        return footroom_subhourly_energy_adjustment_rule(d, mod, prj, tmp)

    m.GenVarStorHyb_Subtimepoint_Curtailment_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=subtimepoint_curtailment_expression_rule
    )

    def subtimepoint_delivered_energy_expression_rule(mod, prj, tmp):
        """
        Sub-hourly energy delivered from providing upward reserves.
        """
        return headroom_subhourly_energy_adjustment_rule(d, mod, prj, tmp)

    m.GenVarStorHyb_Subtimepoint_Energy_Delivered_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=subtimepoint_delivered_energy_expression_rule
    )

    m.GenVarStorHyb_Scheduled_Curtailment_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=scheduled_curtailment_expression_rule
    )

    m.GenVarStorHyb_Total_Curtailment_MW = Expression(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=total_curtailment_expression_rule
    )

    # Constraints
    ###########################################################################

    m.GenVarStorHyb_Max_Power_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=max_power_rule
    )

    m.GenVarStorHyb_Max_Available_Power_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=max_available_power_rule
    )

    m.GenVarStorHyb_Min_Power_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=min_power_rule
    )

    m.GenVarStorHyb_Max_Charge_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=max_charge_rule
    )

    m.GenVarStorHyb_Max_Discharge_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=max_discharge_rule
    )

    m.GenVarStorHyb_Energy_Tracking_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=energy_tracking_rule
    )

    m.GenVarStorHyb_Max_Energy_in_Storage_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=max_energy_in_storage_rule
    )

    m.GenVarStorHyb_Max_Headroom_Energy_Constraint = Constraint(
        m.GEN_VAR_STOR_HYB_OPR_TMPS, rule=max_headroom_energy_rule
    )
Ejemplo n.º 6
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`CARBON_TAX_PRJS`                                               |
    | | *Within*: :code:`PROJECTS`                                            |
    |                                                                         |
    | Two set of carbonaceous projects we need to track for the carbon tax.   |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`carbon_tax_zone`                                               |
    | | *Defined over*: :code:`CARBON_TAX_PRJS`                               |
    | | *Within*: :code:`CARBON_TAX_ZONES`                                    |
    |                                                                         |
    | This param describes the carbon tax zone for each carbon tax project.   |
    +-------------------------------------------------------------------------+
    | | :code:`carbon_tax_allowance`                                          |
    | | *Defined over*: :code:`CARBON_TAX_PRJS`, `CARBON_TAX_PRJ_OPR_PRDS`    |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | This param describes the carbon tax allowance for each carbon tax       |
    | project.                                                                |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Derived Sets                                                            |
    +=========================================================================+
    | | :code:`CARBON_TAX_PRJS_BY_CARBON_TAX_ZONE`                            |
    | | *Defined over*: :code:`CARBON_TAX_ZONES`                              |
    | | *Within*: :code:`CARBON_TAX_PRJS`                                     |
    |                                                                         |
    | Indexed set that describes the list of carbonaceous projects for each   |
    | carbon tax zone.                                                        |
    +-------------------------------------------------------------------------+
    | | :code:`CARBON_TAX_PRJ_OPR_TMPS`                                       |
    | | *Within*: :code:`PRJ_OPR_TMPS`                                        |
    |                                                                         |
    | Two-dimensional set that defines all project-timepoint combinations     |
    | when a carbon tax project can be operational.                           |
    +-------------------------------------------------------------------------+
    | | :code:`CARBON_TAX_PRJ_OPR_PRDS`                                       |
    | | *Within*: :code:`PRJ_OPR_PRDS`                                        |
    |                                                                         |
    | Two-dimensional set that defines all project-period combinations        |
    | when a carbon tax project can be operational.                           |
    +-------------------------------------------------------------------------+

    """

    # Sets
    ###########################################################################

    m.CARBON_TAX_PRJS = Set(within=m.PROJECTS)

    m.CARBON_TAX_PRJ_OPR_TMPS = Set(
        within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: [
            (p, tmp) for (p, tmp) in mod.PRJ_OPR_TMPS if p in mod.CARBON_TAX_PRJS
        ],
    )

    m.CARBON_TAX_PRJ_OPR_PRDS = Set(
        within=m.PRJ_OPR_PRDS,
        initialize=lambda mod: [
            (p, tmp) for (p, tmp) in mod.PRJ_OPR_PRDS if p in mod.CARBON_TAX_PRJS
        ],
    )

    # Input Params
    ###########################################################################

    m.carbon_tax_zone = Param(m.CARBON_TAX_PRJS, within=m.CARBON_TAX_ZONES)

    m.carbon_tax_allowance = Param(
        m.CARBON_TAX_PRJS, m.PERIODS, within=NonNegativeReals, default=0
    )

    # Derived Sets
    ###########################################################################

    m.CARBON_TAX_PRJS_BY_CARBON_TAX_ZONE = Set(
        m.CARBON_TAX_ZONES,
        within=m.CARBON_TAX_PRJS,
        initialize=lambda mod, co2_z: subset_init_by_param_value(
            mod, "CARBON_TAX_PRJS", "carbon_tax_zone", co2_z
        ),
    )

    # Expressions
    ###########################################################################

    def carbon_tax_allowance_rule(mod, prj, tmp):
        """
        Allowance from each project. Multiply by the timepoint duration,
        timepoint weight and power to get the total emissions allowance.
        """

        return (
            mod.Power_Provision_MW[prj, tmp]
            * mod.carbon_tax_allowance[prj, mod.period[tmp]]
        )

    m.Project_Carbon_Tax_Allowance = Expression(
        m.CARBON_TAX_PRJ_OPR_TMPS, rule=carbon_tax_allowance_rule
    )
Ejemplo n.º 7
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`CRBN_PRJS`                                                     |
    | | *Within*: :code:`PROJECTS`                                            |
    |                                                                         |
    | Two set of carbonaceous projects we need to track for the carbon cap.   |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`carbon_cap_zone`                                               |
    | | *Defined over*: :code:`CRBN_PRJS`                                     |
    | | *Within*: :code:`CARBON_CAP_ZONES`                                    |
    |                                                                         |
    | This param describes the carbon cap zone for each carbonaceous project. |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Derived Sets                                                            |
    +=========================================================================+
    | | :code:`CRBN_PRJS_BY_CARBON_CAP_ZONE`                                  |
    | | *Defined over*: :code:`CARBON_CAP_ZONES`                              |
    | | *Within*: :code:`CRBN_PRJS`                                           |
    |                                                                         |
    | Indexed set that describes the list of carbonaceous projects for each   |
    | carbon cap zone.                                                        |
    +-------------------------------------------------------------------------+
    | | :code:`CRBN_PRJ_OPR_TMPS`                                             |
    | | *Within*: :code:`PRJ_OPR_TMPS`                                        |
    |                                                                         |
    | Two-dimensional set that defines all project-timepoint combinations     |
    | when a carbonaceous project can be operational.                         |
    +-------------------------------------------------------------------------+

    """

    # Sets
    ###########################################################################

    m.CRBN_PRJS = Set(within=m.PROJECTS)

    # Input Params
    ###########################################################################

    m.carbon_cap_zone = Param(m.CRBN_PRJS, within=m.CARBON_CAP_ZONES)

    # Derived Sets
    ###########################################################################

    m.CRBN_PRJS_BY_CARBON_CAP_ZONE = Set(
        m.CARBON_CAP_ZONES,
        within=m.CRBN_PRJS,
        initialize=lambda mod, co2_z: subset_init_by_param_value(
            mod, "CRBN_PRJS", "carbon_cap_zone", co2_z))

    m.CRBN_PRJ_OPR_TMPS = Set(
        within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: [(p, tmp) for (p, tmp) in mod.PRJ_OPR_TMPS
                                if p in mod.CRBN_PRJS])
Ejemplo n.º 8
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`DR`                                                            |
    |                                                                         |
    | The set of projects of the :code:`dr` operational type.                 |
    +-------------------------------------------------------------------------+
    | | :code:`DR_OPR_TMPS`                                                   |
    |                                                                         |
    | Two-dimensional set with projects of the :code:`dr`                     |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`DR_OPR_HRZS`                                                   |
    |                                                                         |
    | Two-dimensional set with projects of the :code:`dr`                     |
    | operational type and their operational horizons.                        |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`DR_Shift_Up_MW`                                                |
    | | *Defined over*: :code:`DR_OPR_TMPS`                                   |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Load added (in MW) in each operational timepoint.                       |
    +-------------------------------------------------------------------------+
    | | :code:`DR_Shift_Down_MW`                                              |
    | | *Defined over*: :code:`DR_OPR_TMPS`                                   |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Load removed (in MW) in each operational timepoint.                     |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | | :code:`DR_Max_Shift_Up_Constraint`                                    |
    | | *Defined over*: :code:`DR_OPR_TMPS`                                   |
    |                                                                         |
    | Limits the added load to the available power capacity.                  |
    +-------------------------------------------------------------------------+
    | | :code:`DR_Max_Shift_Down_Constraint`                                  |
    | | *Defined over*: :code:`DR_OPR_TMPS`                                   |
    |                                                                         |
    | Limits the removed load to the available power capacity.                |
    +-------------------------------------------------------------------------+
    | | :code:`DR_Energy_Balance_Constraint`                                  |
    | | *Defined over*: :code:`DR_OPR_HRZS`                                   |
    |                                                                         |
    | Ensures no energy losses or gains when shifting load within the horizon.|
    +-------------------------------------------------------------------------+
    | | :code:`DR_Energy_Budget_Constraint`                                   |
    | | *Defined˚ over*: :code:`DR_OPR_HRZS`                                  |
    |                                                                         |
    | Total energy that can be shifted on each horizon should be less than    |
    | or equal to budget.                                                     |
    +-------------------------------------------------------------------------+

    """

    # Sets
    ###########################################################################

    m.DR = Set(within=m.PROJECTS,
               initialize=lambda mod: subset_init_by_param_value(
                   mod, "PROJECTS", "operational_type", "dr"))

    m.DR_OPR_TMPS = Set(dimen=2,
                        within=m.PRJ_OPR_TMPS,
                        initialize=lambda mod: list(
                            set((g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS
                                if g in mod.DR)))

    m.DR_OPR_HRZS = Set(
        dimen=2,
        initialize=lambda mod: list(
            set((g, mod.horizon[tmp, mod.balancing_type_project[g]])
                for (g, tmp) in mod.PRJ_OPR_TMPS if g in mod.DR)))

    # Variables
    ###########################################################################

    m.DR_Shift_Up_MW = Var(m.DR_OPR_TMPS, within=NonNegativeReals)

    m.DR_Shift_Down_MW = Var(m.DR_OPR_TMPS, within=NonNegativeReals)

    # Constraints
    ###########################################################################

    m.DR_Max_Shift_Up_Constraint = Constraint(m.DR_OPR_TMPS,
                                              rule=max_shift_up_rule)

    m.DR_Max_Shift_Down_Constraint = Constraint(m.DR_OPR_TMPS,
                                                rule=max_shift_down_rule)

    m.DR_Energy_Balance_Constraint = Constraint(m.DR_OPR_HRZS,
                                                rule=energy_balance_rule)

    m.DR_Energy_Budget_Constraint = Constraint(m.DR_OPR_HRZS,
                                               rule=energy_budget_rule)
Ejemplo n.º 9
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_VAR`                                                       |
    |                                                                         |
    | The set of generators of the :code:`gen_var` operational type.          |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_VAR_OPR_TMPS`                                              |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_var`              |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_var_cap_factor`                                            |
    | | *Defined over*: :code:`GEN_VAR`                                       |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | The project's power output in each operational timepoint as a fraction  |
    | of its available capacity (i.e. the capacity factor).                   |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`GenVar_Provide_Power_MW`                                       |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Power provision in MW from this project in each timepoint in which the  |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Expressions                                                             |
    +=========================================================================+
    | | :code:`GenVar_Subhourly_Curtailment_MW`                               |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    |                                                                         |
    | Sub-hourly curtailment (in MW) from providing downward reserves.        |
    +-------------------------------------------------------------------------+
    | | :code:`GenVar_Subhourly_Energy_Delivered_MW`                          |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    |                                                                         |
    | Sub-hourly energy delivered (in MW) from providing upward reserves.     |
    +-------------------------------------------------------------------------+
    | | :code:`GenVar_Scheduled_Curtailment_MW`                               |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    |                                                                         |
    | The available power minus what was actually provided (in MW).           |
    +-------------------------------------------------------------------------+
    | | :code:`GenVar_Total_Curtailment_MW`                                   |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    |                                                                         |
    | Scheduled curtailment (in MW) plus an upward adjustment for additional  |
    | curtailment when providing downward reserves, and a downward adjustment |
    | adjustment for a reduction in curtailment when providing upward         |
    | reserves, to account for sub-hourly dispatch when providing reserves.   |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | Power                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenVar_Max_Power_Constraint`                                   |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    |                                                                         |
    | Limits the power plus upward reserves in each timepoint based on the    |
    | :code:`gen_var_cap_factor` and the available capacity.                  |
    +-------------------------------------------------------------------------+
    | | :code:`GenVar_Min_Power_Constraint`                                   |
    | | *Defined over*: :code:`GEN_VAR_OPR_TMPS`                              |
    |                                                                         |
    | Power provision minus downward reserves should exceed zero.             |
    +-------------------------------------------------------------------------+

    """

    # Sets
    ###########################################################################
    m.GEN_VAR = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "gen_var"
        ),
    )

    m.GEN_VAR_OPR_TMPS = Set(
        dimen=2,
        within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: list(
            set((g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS if g in mod.GEN_VAR)
        ),
    )

    # Required Params
    ###########################################################################

    m.gen_var_cap_factor = Param(m.GEN_VAR_OPR_TMPS, within=Reals)

    # Variables
    ###########################################################################

    m.GenVar_Provide_Power_MW = Var(m.GEN_VAR_OPR_TMPS, within=NonNegativeReals)

    # Expressions
    ###########################################################################

    def upwards_reserve_rule(mod, g, tmp):
        """
        Gather all headroom variables, and de-rate the total reserves offered
        to account for the fact that gen_var output is uncertain.
        """
        return sum(
            getattr(mod, c)[g, tmp]
            / getattr(mod, getattr(d, reserve_variable_derate_params)[c])[g]
            for c in getattr(d, headroom_variables)[g]
        )

    m.GenVar_Upwards_Reserves_MW = Expression(
        m.GEN_VAR_OPR_TMPS, rule=upwards_reserve_rule
    )

    def downwards_reserve_rule(mod, g, tmp):
        """
        Gather all footroom variables, and de-rate the total reserves offered
        to account for the fact that gen_var output is uncertain.
        """
        return sum(
            getattr(mod, c)[g, tmp]
            / getattr(mod, getattr(d, reserve_variable_derate_params)[c])[g]
            for c in getattr(d, footroom_variables)[g]
        )

    m.GenVar_Downwards_Reserves_MW = Expression(
        m.GEN_VAR_OPR_TMPS, rule=downwards_reserve_rule
    )

    def subhourly_curtailment_expression_rule(mod, g, tmp):
        """
        Sub-hourly curtailment from providing downward reserves.
        """
        return footroom_subhourly_energy_adjustment_rule(d, mod, g, tmp)

    m.GenVar_Subhourly_Curtailment_MW = Expression(
        m.GEN_VAR_OPR_TMPS, rule=subhourly_curtailment_expression_rule
    )

    def subhourly_delivered_energy_expression_rule(mod, g, tmp):
        """
        Sub-hourly energy delivered from providing upward reserves.
        """
        return headroom_subhourly_energy_adjustment_rule(d, mod, g, tmp)

    m.GenVar_Subhourly_Energy_Delivered_MW = Expression(
        m.GEN_VAR_OPR_TMPS, rule=subhourly_delivered_energy_expression_rule
    )

    m.GenVar_Scheduled_Curtailment_MW = Expression(
        m.GEN_VAR_OPR_TMPS, rule=scheduled_curtailment_expression_rule
    )

    m.GenVar_Total_Curtailment_MW = Expression(
        m.GEN_VAR_OPR_TMPS, rule=total_curtailment_expression_rule
    )

    # Constraints
    ###########################################################################

    m.GenVar_Max_Power_Constraint = Constraint(m.GEN_VAR_OPR_TMPS, rule=max_power_rule)

    m.GenVar_Min_Power_Constraint = Constraint(m.GEN_VAR_OPR_TMPS, rule=min_power_rule)
Ejemplo n.º 10
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`STOR`                                                          |
    |                                                                         |
    | The set of projects of the :code:`stor` operational type.               |
    +-------------------------------------------------------------------------+
    | | :code:`STOR_OPR_TMPS`                                                 |
    |                                                                         |
    | Two-dimensional set with projects of the :code:`stor`                   |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`STOR_LINKED_TMPS`                                              |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`stor`                 |
    | operational type and their linked timepoints.                           |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`stor_charging_efficiency`                                      |
    | | *Defined over*: :code:`STOR`                                          |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The storage project's charging efficiency (1 = 100% efficient).         |
    +-------------------------------------------------------------------------+
    | | :code:`stor_discharging_efficiency`                                   |
    | | *Defined over*: :code:`STOR`                                          |
    | | *Within*: :code:`PercentFraction`                                     |
    |                                                                         |
    | The storage project's discharging efficiency (1 = 100% efficient).      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Optional Input Params                                                   |
    +=========================================================================+
    | | :code:`stor_losses_factor_in_rps`                                     |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The fraction of storage losses that count against the RPS target.       |
    +-------------------------------------------------------------------------+
    | | :code:`stor_charging_capacity_multiplier`                             |
    | | *Defined over*: :code:`STOR`                                          |
    | | *Within*: :code:`NonNegativeReals`                                    |
    | | *Default*: :code:`1.0`                                                |
    |                                                                         |
    | The storage project's charging capacity multiplier to be used if the    |
    | charging capacity is different from the nameplate capacity.             |
    +-------------------------------------------------------------------------+
    | | :code:`stor_discharging_capacity_multiplier`                          |
    | | *Defined over*: :code:`STOR`                                          |
    | | *Within*: :code:`NonNegativeReals`                                    |
    | | *Default*: :code:`1.0`                                                |
    |                                                                         |
    | The storage project's discharging capacity multiplier to be used if the |
    | discharging capacity is different from the nameplate capacity.          |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Linked Input Params                                                     |
    +=========================================================================+
    | | :code:`stor_linked_starting_energy_in_storage`                        |
    | | *Defined over*: :code:`STOR_LINKED_TMPS`                              |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's starting energy in storage in the linked timepoints.      |
    +-------------------------------------------------------------------------+
    | | :code:`stor_linked_discharge`                                         |
    | | *Defined over*: :code:`STOR_LINKED_TMPS`                              |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's dicharging in the linked timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`stor_linked_charge`                                            |
    | | *Defined over*: :code:`STOR_LINKED_TMPS`                              |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's charging in the linked timepoints.                        |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`Stor_Charge_MW`                                                |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Charging power in MW from this project in each timepoint in which the   |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Discharge_MW`                                             |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | Discharging power in MW from this project in each timepoint in which the|
    |  project is operational (capacity exists and the project is available). |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Starting_Energy_in_Storage_MWh`                           |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The state of charge of the storage project at the start of each         |
    | timepoint, in MWh of energy stored.                                     |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | Power and Stage of Charge                                               |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Charge_Constraint`                                    |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Limits the project's charging power to the available capacity.          |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Discharge_Constraint`                                 |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Limits the project's discharging power to the available capacity.       |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Energy_Tracking_Constraint`                               |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Tracks the amount of energy stored in each timepoint based on the       |
    | previous timepoint's energy stored and the charge and discharge         |
    | decisions.                                                              |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Energy_in_Storage_Constraint`                         |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Limits the project's total energy stored to the available energy        |
    | capacity.                                                               |
    +-------------------------------------------------------------------------+
    | Reserves                                                                |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Headroom_Power_Constraint`                            |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Limits the project's upward reserves based on available headroom.       |
    | Going from charging to non-charging also counts as headroom, doubling   |
    | the maximum amount of potential headroom.                               |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Footroom_Power_Constraint`                            |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Limits the project's downward reserves based on available footroom.     |
    | Going from non-charging to charging also counts as footroom, doubling   |
    | the maximum amount of potential footroom.                               |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Headroom_Energy_Constraint`                           |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Can't provide more upward reserves (times sustained duration required)  |
    |than available energy in storage in that timepoint.                      |
    +-------------------------------------------------------------------------+
    | | :code:`Stor_Max_Footroom_Energy_Constraint`                           |
    | | *Defined over*: :code:`STOR_OPR_TMPS`                                 |
    |                                                                         |
    | Can't provide more downard reserves (times sustained duration required) |
    | than available capacity to store energy in that timepoint.              |
    +-------------------------------------------------------------------------+



    """

    # Sets
    ###########################################################################

    m.STOR = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "stor"
        )
    )

    m.STOR_OPR_TMPS = Set(
        dimen=2, within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: list(
            set((g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS
                if g in mod.STOR)
        )
    )

    m.STOR_LINKED_TMPS = Set(dimen=2)

    # Required Params
    ###########################################################################

    m.stor_charging_efficiency = Param(
        m.STOR, within=PercentFraction
    )

    m.stor_discharging_efficiency = Param(
        m.STOR, within=PercentFraction
    )

    m.stor_charging_capacity_multiplier = Param(
        m.STOR, within=NonNegativeReals, default=1.0
    )

    m.stor_discharging_capacity_multiplier = Param(
        m.STOR, within=NonNegativeReals, default=1.0
    )

    # Optional Params
    ###########################################################################

    m.stor_losses_factor_in_rps = Param(default=1)

    # Linked Params
    ###########################################################################

    m.stor_linked_starting_energy_in_storage = Param(
        m.STOR_LINKED_TMPS,
        within=NonNegativeReals
    )

    m.stor_linked_discharge = Param(
        m.STOR_LINKED_TMPS,
        within=NonNegativeReals
    )

    m.stor_linked_charge = Param(
        m.STOR_LINKED_TMPS,
        within=NonNegativeReals
    )

    # Variables
    ###########################################################################

    m.Stor_Charge_MW = Var(
        m.STOR_OPR_TMPS,
        within=NonNegativeReals
    )

    m.Stor_Discharge_MW = Var(
        m.STOR_OPR_TMPS,
        within=NonNegativeReals
    )

    m.Stor_Starting_Energy_in_Storage_MWh = Var(
        m.STOR_OPR_TMPS,
        within=NonNegativeReals
    )

    # Expressions
    ###########################################################################

    def upward_reserve_rule(mod, g, tmp):
        return sum(getattr(mod, c)[g, tmp]
                   for c in getattr(d, headroom_variables)[g])
    m.Stor_Upward_Reserves_MW = Expression(
        m.STOR_OPR_TMPS,
        rule=upward_reserve_rule
    )

    def downward_reserve_rule(mod, g, tmp):
        return sum(getattr(mod, c)[g, tmp]
                   for c in getattr(d, footroom_variables)[g])
    m.Stor_Downward_Reserves_MW = Expression(
        m.STOR_OPR_TMPS,
        rule=downward_reserve_rule
    )

    # Constraints
    ###########################################################################

    # Power and State of Charge
    m.Stor_Max_Charge_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_charge_rule
    )

    m.Stor_Max_Discharge_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_discharge_rule
    )

    m.Stor_Energy_Tracking_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=energy_tracking_rule
    )

    m.Stor_Max_Energy_in_Storage_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_energy_in_storage_rule
    )

    # Reserves
    m.Stor_Max_Headroom_Power_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_headroom_power_rule
    )

    m.Stor_Max_Footroom_Power_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_footroom_power_rule
    )

    m.Stor_Max_Headroom_Energy_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_headroom_energy_rule
    )

    m.Stor_Max_Footroom_Energy_Constraint = Constraint(
        m.STOR_OPR_TMPS,
        rule=max_footroom_energy_rule
    )
Ejemplo n.º 11
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_HYDRO_MUST_TAKE`                                           |
    |                                                                         |
    | The set of generators of the :code:`gen_hydro_must_take` operational    |
    | type.                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                                  |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_hydro_must_take`  |
    | operational type and their operational horizons.                        |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_HYDRO_MUST_TAKE_OPR_TMPS`                                  |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_hydro_must_take`  |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_HYDRO_MUST_TAKE_LINKED_TMPS`                               |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_hydro_must_take`  |
    | operational type and their linked timepoints.                           |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_hydro_must_take_max_power_fraction`                        |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                  |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | The project's maximum power output in each operational horizon as a     |
    | fraction of its available capacity.                                     |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_min_power_fraction`                        |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                  |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | The project's minimum power output in each operational horizon as a     |
    | fraction of its available capacity.                                     |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_average_power_fraction`                    |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                  |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | The project's avarage power output in each operational horizon as a     |
    | fraction of its available capacity. This can be interpreted as the      |
    | project's average capacity factor or plant load factor.                 |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Optional Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_hydro_must_take_ramp_up_when_on_rate`                      |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE`                           |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's upward ramp rate limit during operations, defined as a    |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_ramp_down_when_on_rate`                    |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE`                           |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`1`                                                  |
    |                                                                         |
    | The project's downward ramp rate limit during operations, defined as a  |
    | fraction of its capacity per minute.                                    |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_aux_consumption_frac_capacity`             |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE`                           |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`0`                                                  |
    |                                                                         |
    | Auxiliary consumption as a fraction of capacity. This would be          |
    | incurred in all timepoints when capacity is available.                  |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_aux_consumption_frac_power`                |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE`                           |
    | | *Within*: :code:`PercentFraction`                                     |
    | | *Default*: :code:`0`                                                  |
    |                                                                         |
    | Auxiliary consumption as a fraction of gross power output.              |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Linked Input Params                                                     |
    +=========================================================================+
    | | :code:`gen_hydro_must_take_linked_power`                              |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_LINKED_TMPS`               |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | The project's power provision in the linked timepoints.                 |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_linked_upwards_reserves`                   |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_LINKED_TMPS`               |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's upward reserve provision in the linked timepoints.        |
    +-------------------------------------------------------------------------+
    | | :code:`gen_hydro_must_take_linked_downwards_reserves`                 |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_LINKED_TMPS`               |
    | | *Within*: :code:`NonNegativeReals`                                    |
    |                                                                         |
    | The project's downward reserve provision in the linked timepoints.      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Variables                                                               |
    +=========================================================================+
    | | :code:`GenHydroMustTake_Gross_Power_MW`                               |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_TMPS`                  |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | Power provision in MW from this project in each timepoint in which the  |
    | project is operational (capacity exists and the project is available).  |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Expressions                                                             |
    +=========================================================================+
    | | :code:`GenHydroMustTake_Auxiliary_Consumption_MW`                     |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_TMPS`                  |
    |                                                                         |
    | The project's auxiliary consumption (power consumed on-site and not     |
    | sent to the grid) in each timepoint.                                    |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | Power                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydroMustTake_Max_Power_Constraint`                         |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                  |
    |                                                                         |
    | Limits the power plus upward reserves based on the                      |
    | :code:`gen_hydro_must_take_max_power_fraction` and the available        |
    | capacity.                                                               |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydroMustTake_Min_Power_Constraint`                         |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                  |
    |                                                                         |
    | Power provision minus downward reserves should exceed a certain level   |
    | based on the :code:`gen_hydro_must_take_min_power_fraction` and the     |
    | available capacity.                                                     |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydroMustTake_Energy_Budget_Constraint`                     |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_HRZS`                  |
    |                                                                         |
    | The project's average capacity factor in each operational horizon,      |
    | should match the specified                                              |
    | :code:`gen_hydro_must_take_average_power_fraction`.                     |
    +-------------------------------------------------------------------------+
    | Ramps                                                                   |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydroMustTake_Ramp_Up_Constraint`                           |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_TMPS`                  |
    |                                                                         |
    | Limits the allowed project upward ramp based on the                     |
    | :code:`gen_hydro_must_take_ramp_up_when_on_rate`.                       |
    +-------------------------------------------------------------------------+
    | | :code:`GenHydroMustTake_Ramp_Down_Constraint`                         |
    | | *Defined over*: :code:`GEN_HYDRO_MUST_TAKE_OPR_TMPS`                  |
    |                                                                         |
    | Limits the allowed project downward ramp based on the                   |
    | :code:`gen_hydro_must_take_ramp_down_when_on_rate`.                     |
    +-------------------------------------------------------------------------+

    """
    # Sets
    ###########################################################################

    m.GEN_HYDRO_MUST_TAKE = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "gen_hydro_must_take"),
    )

    m.GEN_HYDRO_MUST_TAKE_OPR_HRZS = Set(dimen=2)

    m.GEN_HYDRO_MUST_TAKE_OPR_TMPS = Set(
        dimen=2,
        within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: list(
            set((g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS
                if g in mod.GEN_HYDRO_MUST_TAKE)),
    )

    m.GEN_HYDRO_MUST_TAKE_LINKED_TMPS = Set(dimen=2)

    # Required Params
    ###########################################################################

    m.gen_hydro_must_take_max_power_fraction = Param(
        m.GEN_HYDRO_MUST_TAKE_OPR_HRZS, within=Reals)

    m.gen_hydro_must_take_min_power_fraction = Param(
        m.GEN_HYDRO_MUST_TAKE_OPR_HRZS, within=Reals)

    m.gen_hydro_must_take_average_power_fraction = Param(
        m.GEN_HYDRO_MUST_TAKE_OPR_HRZS, within=Reals)

    # Optional Params
    ###########################################################################

    m.gen_hydro_must_take_ramp_up_when_on_rate = Param(m.GEN_HYDRO_MUST_TAKE,
                                                       within=PercentFraction,
                                                       default=1)

    m.gen_hydro_must_take_ramp_down_when_on_rate = Param(
        m.GEN_HYDRO_MUST_TAKE, within=PercentFraction, default=1)

    m.gen_hydro_must_take_aux_consumption_frac_capacity = Param(
        m.GEN_HYDRO_MUST_TAKE, within=PercentFraction, default=0)

    m.gen_hydro_must_take_aux_consumption_frac_power = Param(
        m.GEN_HYDRO_MUST_TAKE, within=PercentFraction, default=0)

    # Linked Params
    ###########################################################################

    m.gen_hydro_must_take_linked_power = Param(
        m.GEN_HYDRO_MUST_TAKE_LINKED_TMPS, within=Reals)

    m.gen_hydro_must_take_linked_upwards_reserves = Param(
        m.GEN_HYDRO_MUST_TAKE_LINKED_TMPS, within=NonNegativeReals)

    m.gen_hydro_must_take_linked_downwards_reserves = Param(
        m.GEN_HYDRO_MUST_TAKE_LINKED_TMPS, within=NonNegativeReals)

    # Variables
    ###########################################################################

    m.GenHydroMustTake_Gross_Power_MW = Var(m.GEN_HYDRO_MUST_TAKE_OPR_TMPS,
                                            within=Reals)

    # Expressions
    ###########################################################################

    def upwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, headroom_variables)[g])

    m.GenHydroMustTake_Upwards_Reserves_MW = Expression(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=upwards_reserve_rule)

    def downwards_reserve_rule(mod, g, tmp):
        return sum(
            getattr(mod, c)[g, tmp] for c in getattr(d, footroom_variables)[g])

    m.GenHydroMustTake_Downwards_Reserves_MW = Expression(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=downwards_reserve_rule)

    def auxiliary_consumption_rule(mod, g, tmp):
        """
        **Expression Name**: GenHydroMustTake_Auxiliary_Consumption_MW
        **Defined Over**: GEN_HYDRO_MUST_TAKE_OPR_TMPS
        """
        return (mod.Capacity_MW[g, mod.period[tmp]] *
                mod.Availability_Derate[g, tmp] *
                mod.gen_hydro_must_take_aux_consumption_frac_capacity[g] +
                mod.GenHydroMustTake_Gross_Power_MW[g, tmp] *
                mod.gen_hydro_must_take_aux_consumption_frac_power[g])

    m.GenHydroMustTake_Auxiliary_Consumption_MW = Expression(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=auxiliary_consumption_rule)

    # Constraints
    ###########################################################################

    m.GenHydroMustTake_Max_Power_Constraint = Constraint(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=max_power_rule)

    m.GenHydroMustTake_Min_Power_Constraint = Constraint(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=min_power_rule)

    m.GenHydroMustTake_Energy_Budget_Constraint = Constraint(
        m.GEN_HYDRO_MUST_TAKE_OPR_HRZS, rule=energy_budget_rule)

    m.GenHydroMustTake_Ramp_Up_Constraint = Constraint(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=ramp_up_rule)

    m.GenHydroMustTake_Ramp_Down_Constraint = Constraint(
        m.GEN_HYDRO_MUST_TAKE_OPR_TMPS, rule=ramp_down_rule)
Ejemplo n.º 12
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """

    :param m:
    :param d:
    :return:
    """
    # Which projects contribute to the ELCC surface
    m.contributes_to_elcc_surface = Param(m.PRM_PROJECTS, within=Binary)

    m.ELCC_SURFACE_PROJECTS = Set(
        within=m.PRM_PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PRM_PROJECTS", "contributes_to_elcc_surface", 1
        ),
    )

    m.elcc_surface_cap_factor = Param(m.ELCC_SURFACE_PROJECTS, within=NonNegativeReals)

    m.ELCC_SURFACE_PROJECTS_BY_PRM_ZONE = Set(
        m.PRM_ZONES,
        within=m.ELCC_SURFACE_PROJECTS,
        initialize=lambda mod, prm_z: subset_init_by_param_value(
            mod, "ELCC_SURFACE_PROJECTS", "prm_zone", prm_z
        ),
    )

    # Define the ELCC surface
    # Surface is limited to 1000 facets
    m.PROJECT_PERIOD_ELCC_SURFACE_FACETS = Set(
        dimen=3, within=m.ELCC_SURFACE_PROJECTS * m.PERIODS * list(range(1, 1001))
    )

    # The project coefficient for the surface
    # This goes into the piecewise linear constraint for the aggregate ELCC
    # calculation; unless we have a very detailed surface, this coefficient
    # would actually likely only vary by technology (e.g. wind and solar for a
    # 2-dimensional surface), but we have it by project here for maximum
    # flexibility
    m.elcc_surface_coefficient = Param(
        m.PROJECT_PERIOD_ELCC_SURFACE_FACETS, within=NonNegativeReals
    )

    m.PRM_ZONE_PERIODS_FOR_ELCC_SURFACE = Set(within=m.PRM_ZONES * m.PERIODS)

    # Loads for normalization
    m.prm_peak_load_mw = Param(
        m.PRM_ZONE_PERIODS_FOR_ELCC_SURFACE, within=NonNegativeReals
    )
    m.prm_annual_load_mwh = Param(
        m.PRM_ZONE_PERIODS_FOR_ELCC_SURFACE, within=NonNegativeReals
    )

    # ELCC surface contribution of each project
    def elcc_surface_contribution_rule(mod, prj, p, f):
        """

        :param mod:
        :param prj:
        :param p:
        :param f:
        :return:
        """
        if (prj, p) in mod.PRJ_OPR_PRDS:
            return (
                mod.elcc_surface_coefficient[prj, p, f]
                * mod.prm_peak_load_mw[mod.prm_zone[prj], p]
                * mod.ELCC_Eligible_Capacity_MW[prj, p]
                * 8760
                * mod.elcc_surface_cap_factor[prj]
                / mod.prm_annual_load_mwh[mod.prm_zone[prj], p]
            )
        else:
            return 0

    m.ELCC_Surface_Contribution_MW = Expression(
        m.PROJECT_PERIOD_ELCC_SURFACE_FACETS, rule=elcc_surface_contribution_rule
    )
Ejemplo n.º 13
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_MUST_RUN`                                                  |
    |                                                                         |
    | The set of generators of the :code:`gen_must_run` operational type.     |
    +-------------------------------------------------------------------------+
    | | :code:`GEN_MUST_RUN_OPR_TMPS`                                         |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_must_run`         |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | | :code:`GenMustRun_No_Upward_Reserves_Constraint`                      |
    | | *Defined over*: :code:`GEN_MUST_RUN_OPR_TMPS`                         |
    |                                                                         |
    | Must-run projects cannot provide upward reserves.                       |
    +-------------------------------------------------------------------------+
    | | :code:`GenMustRun_No_Downward_Reserves_Constraint`                    |
    | | *Defined over*: :code:`GEN_MUST_RUN_OPR_TMPS`                         |
    |                                                                         |
    | Must-run projects cannot provide downward reserves.                     |
    +-------------------------------------------------------------------------+


    """

    # Sets
    ###########################################################################

    m.GEN_MUST_RUN = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "gen_must_run"))

    m.GEN_MUST_RUN_OPR_TMPS = Set(dimen=2,
                                  within=m.PRJ_OPR_TMPS,
                                  initialize=lambda mod: list(
                                      set((g, tmp)
                                          for (g, tmp) in mod.PRJ_OPR_TMPS
                                          if g in mod.GEN_MUST_RUN)))

    # Constraints
    ###########################################################################

    # TODO: remove this constraint once input validation is in place that
    #  does not allow specifying a reserve_zone if 'gen_must_run' type
    def no_upward_reserve_rule(mod, g, tmp):
        """
        **Constraint Name**: GenMustRun_No_Upward_Reserves_Constraint
        **Enforced Over**: GEN_MUST_RUN_OPR_TMPS

        Upward reserves should be zero in every operational timepoint.
        """
        if getattr(d, headroom_variables)[g]:
            warnings.warn(
                """project {} is of the 'gen_must_run' operational type and 
                should not be assigned any upward reserve BAs since it cannot 
                provide upward reserves. Please replace the upward reserve BA 
                for project {} with '.' (no value) in projects.tab. Model will 
                add constraint to ensure project {} cannot provide upward 
                reserves.
                """.format(g, g, g))
            return sum(
                getattr(mod, c)[g, tmp]
                for c in getattr(d, headroom_variables)[g]) == 0
        else:
            return Constraint.Skip

    m.GenMustRun_No_Upward_Reserves_Constraint = Constraint(
        m.GEN_MUST_RUN_OPR_TMPS, rule=no_upward_reserve_rule)

    # TODO: remove this constraint once input validation is in place that
    #  does not allow specifying a reserve_zone if 'gen_must_run' type
    def no_downward_reserve_rule(mod, g, tmp):
        """
        **Constraint Name**: GenMustRun_No_Downward_Reserves_Constraint
        **Enforced Over**: GEN_MUST_RUN_OPR_TMPS

        Downward reserves should be zero in every operational timepoint.
        """
        if getattr(d, footroom_variables)[g]:
            warnings.warn(
                """project {} is of the 'gen_must_run' operational type and 
                should not be assigned any downward reserve BAs since it cannot
                provide upwards reserves. Please replace the downward reserve 
                BA for project {} with '.' (no value) in projects.tab. Model 
                will add constraint to ensure project {} cannot provide 
                downward reserves.
                """.format(g, g, g))
            return sum(
                getattr(mod, c)[g, tmp]
                for c in getattr(d, footroom_variables)[g]) == 0
        else:
            return Constraint.Skip

    m.GenMustRun_No_Downward_Reserves_Constraint = Constraint(
        m.GEN_MUST_RUN_OPR_TMPS, rule=no_downward_reserve_rule)
Ejemplo n.º 14
0
def add_model_components(m, d, scenario_directory, subproblem, stage):
    """
    The following Pyomo model components are defined in this module:

    +-------------------------------------------------------------------------+
    | Sets                                                                    |
    +=========================================================================+
    | | :code:`GEN_VAR_MUST_TAKE`                                             |
    |                                                                         |
    | The set of generators of the :code:`gen_var_must_take` operational type.|
    +-------------------------------------------------------------------------+
    | | :code:`GEN_VAR_MUST_TAKE_OPR_TMPS`                                    |
    |                                                                         |
    | Two-dimensional set with generators of the :code:`gen_var_must_take`    |
    | operational type and their operational timepoints.                      |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Required Input Params                                                   |
    +=========================================================================+
    | | :code:`gen_var_must_take_cap_factor`                                  |
    | | *Defined over*: :code:`GEN_VAR_MUST_TAKE`                             |
    | | *Within*: :code:`Reals`                                               |
    |                                                                         |
    | The project's power output in each operational timepoint as a fraction  |
    | of its available capacity (i.e. the capacity factor).                   |
    +-------------------------------------------------------------------------+

    |

    +-------------------------------------------------------------------------+
    | Constraints                                                             |
    +=========================================================================+
    | | :code:`GenVarMustTake_No_Upward_Reserves_Constraint`                  |
    | | *Defined over*: :code:`GEN_VAR_MUST_TAKE_OPR_TMPS`                    |
    |                                                                         |
    | Variable must-take generator projects cannot provide upward reserves.   |
    +-------------------------------------------------------------------------+
    | | :code:`GenVarMustTake_No_Downward_Reserves_Constraint`                |
    | | *Defined over*: :code:`GEN_VAR_MUST_TAKE_OPR_TMPS`                    |
    |                                                                         |
    | Variable must-take generator projects cannot provide downward reserves. |
    +-------------------------------------------------------------------------+


    """

    # Sets
    ###########################################################################

    m.GEN_VAR_MUST_TAKE = Set(
        within=m.PROJECTS,
        initialize=lambda mod: subset_init_by_param_value(
            mod, "PROJECTS", "operational_type", "gen_var_must_take"
        ),
    )

    m.GEN_VAR_MUST_TAKE_OPR_TMPS = Set(
        dimen=2,
        within=m.PRJ_OPR_TMPS,
        initialize=lambda mod: list(
            set((g, tmp) for (g, tmp) in mod.PRJ_OPR_TMPS if g in mod.GEN_VAR_MUST_TAKE)
        ),
    )

    # Required Params
    ###########################################################################

    m.gen_var_must_take_cap_factor = Param(m.GEN_VAR_MUST_TAKE_OPR_TMPS, within=Reals)

    # Constraints
    ###########################################################################

    # TODO: remove this constraint once input validation is in place that
    #  does not allow specifying a reserve_zone if 'gen_var_must_take' type
    def no_upward_reserve_rule(mod, g, tmp):
        """
        **Constraint Name**: GenVarMustTake_No_Upward_Reserves_Constraint
        **Enforced Over**: GEN_VAR_MUST_TAKE_OPR_TMPS

        Upward reserves should be zero in every operational timepoint.
        """
        if getattr(d, headroom_variables)[g]:
            warnings.warn(
                """project {} is of the 'gen_var_must_take' operational 
                type and should not be assigned any upward reserve BAs since it 
                cannot provide  upward reserves. Please replace the upward 
                reserve BA for project {} with '.' (no value) in projects.tab. 
                Model will add  constraint to ensure project {} cannot provide 
                upward reserves
                """.format(
                    g, g, g
                )
            )
            return (
                sum(getattr(mod, c)[g, tmp] for c in getattr(d, headroom_variables)[g])
                == 0
            )
        else:
            return Constraint.Skip

    m.GenVarMustTake_No_Upward_Reserves_Constraint = Constraint(
        m.GEN_VAR_MUST_TAKE_OPR_TMPS, rule=no_upward_reserve_rule
    )

    # TODO: remove this constraint once input validation is in place that
    #  does not allow specifying a reserve_zone if 'gen_var_must_take' type
    def no_downward_reserve_rule(mod, g, tmp):
        """
        **Constraint Name**: GenVarMustTake_No_Downward_Reserves_Constraint
        **Enforced Over**: GEN_VAR_MUST_TAKE_OPR_TMPS

        Downward reserves should be zero in every operational timepoint.
        """
        if getattr(d, footroom_variables)[g]:
            warnings.warn(
                """project {} is of the 'gen_var_must_take' operational 
                type and should not be assigned any downward reserve BAs since 
                it cannot provide downward reserves. Please replace the
                downward reserve BA for project {} with '.' (no value) in 
                projects.tab. Model will add constraint to ensure project {} 
                cannot provide downward reserves.
                """.format(
                    g, g, g
                )
            )
            return (
                sum(getattr(mod, c)[g, tmp] for c in getattr(d, footroom_variables)[g])
                == 0
            )
        else:
            return Constraint.Skip

    m.GenVarMustTake_No_Downward_Reserves_Constraint = Constraint(
        m.GEN_VAR_MUST_TAKE_OPR_TMPS, rule=no_downward_reserve_rule
    )