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])
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)
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)
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)
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 )
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 )
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])
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)
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)
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 )
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)
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 )
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)
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 )