def energy_tracking_rule(mod, s, tmp): """ **Constraint Name**: GenVarStorHyb_Energy_Tracking_Constraint **Enforced Over**: 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). """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s] ) and check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s], boundary_type="linear", ): return Constraint.Skip else: if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s] ) and check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s], boundary_type="linked", ): prev_tmp_hrs_in_tmp = mod.hrs_in_linked_tmp[0] prev_tmp_starting_energy_in_storage = ( mod.gen_var_stor_hyb_linked_starting_energy_in_storage[s, 0] ) prev_tmp_discharge = mod.gen_var_stor_hyb_linked_discharge[s, 0] prev_tmp_charge = mod.gen_var_stor_hyb_linked_charge[s, 0] else: prev_tmp_hrs_in_tmp = mod.hrs_in_tmp[ mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] prev_tmp_starting_energy_in_storage = ( mod.GenVarStorHyb_Starting_Energy_in_Storage_MWh[ s, mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] ) prev_tmp_discharge = mod.GenVarStorHyb_Discharge_MW[ s, mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] prev_tmp_charge = mod.GenVarStorHyb_Charge_MW[ s, mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] return ( mod.GenVarStorHyb_Starting_Energy_in_Storage_MWh[s, tmp] == prev_tmp_starting_energy_in_storage + prev_tmp_charge * prev_tmp_hrs_in_tmp * mod.gen_var_stor_hyb_charging_efficiency[s] - prev_tmp_discharge * prev_tmp_hrs_in_tmp / mod.gen_var_stor_hyb_discharging_efficiency[s] )
def energy_tracking_rule(mod, s, tmp): """ **Constraint Name**: Stor_Energy_Tracking_Constraint **Enforced Over**: STOR_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). """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s] ) and check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s], boundary_type="linear" ): return Constraint.Skip else: if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s] ) and check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[s], boundary_type="linked" ): prev_tmp_hrs_in_tmp = mod.hrs_in_linked_tmp[0] prev_tmp_starting_energy_in_storage = \ mod.stor_linked_starting_energy_in_storage[s, 0] prev_tmp_discharge = mod.stor_linked_discharge[s, 0] prev_tmp_charge = mod.stor_linked_charge[s, 0] else: prev_tmp_hrs_in_tmp = mod.hrs_in_tmp[ mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] prev_tmp_starting_energy_in_storage = \ mod.Stor_Starting_Energy_in_Storage_MWh[ s, mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] prev_tmp_discharge = \ mod.Stor_Discharge_MW[ s, mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] prev_tmp_charge = \ mod.Stor_Charge_MW[ s, mod.prev_tmp[tmp, mod.balancing_type_project[s]] ] return \ mod.Stor_Starting_Energy_in_Storage_MWh[s, tmp] \ == prev_tmp_starting_energy_in_storage \ + prev_tmp_charge * prev_tmp_hrs_in_tmp \ * mod.stor_charging_efficiency[s] \ - prev_tmp_discharge * prev_tmp_hrs_in_tmp \ / mod.stor_discharging_efficiency[s]
def power_delta_rule(mod, p, tmp): """ This rule is only used in tuning costs, so fine to skip for linked horizon's first timepoint. """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[p] ) and (check_boundary_type(mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[p], boundary_type="linear") or check_boundary_type(mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[p], boundary_type="linked")): pass else: return (mod.DR_Shift_Up_MW[p, tmp] - mod.DR_Shift_Down_MW[p, tmp]) - \ (mod.DR_Shift_Up_MW[ p, mod.prev_tmp[tmp, mod.balancing_type_project[p]] ] - mod.DR_Shift_Down_MW[ p, mod.prev_tmp[tmp, mod.balancing_type_project[p]] ])
def power_delta_rule(mod, g, tmp): """ This rule is only used in tuning costs, so fine to skip for linked horizon's first timepoint. """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g] ) and ( check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linear" ) or check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linked" ) ): pass else: return (mod.Stor_Discharge_MW[g, tmp] - mod.Stor_Charge_MW[g, tmp]) \ - (mod.Stor_Discharge_MW[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]] - mod.Stor_Charge_MW[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]])
def power_delta_rule(mod, g, tmp): """ Curtailment is counted as part of the ramp here; excludes any ramping from reserve provision. This rule is only used in tuning costs, so fine to skip for linked horizon's first timepoint. """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g] ) and ( check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linear" ) or check_boundary_type( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linked" ) ): pass else: return \ (mod.Capacity_MW[g, mod.period[tmp]] * mod.Availability_Derate[g, tmp] * mod.gen_var_cap_factor[g, tmp]) \ - (mod.Capacity_MW[g, mod.period[mod.prev_tmp[ tmp, mod.balancing_type_project[g]]]] * mod.Availability_Derate[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]] * mod.gen_var_cap_factor[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]])
def power_delta_rule(mod, g, tmp): """ Exogenously defined ramp for variable must-take generators. This rule is only used in tuning costs, so fine to skip for linked horizon's first timepoint. """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g] ) and (check_boundary_type(mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linear") or check_boundary_type(mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linked")): pass else: return \ (mod.Capacity_MW[g, mod.period[tmp]] * mod.Availability_Derate[g, tmp] * mod.gen_var_must_take_cap_factor[g, tmp]) \ - (mod.Capacity_MW[g, mod.period[mod.prev_tmp[ tmp, mod.balancing_type_project[g]]]] * mod.Availability_Derate[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]] * mod.gen_var_must_take_cap_factor[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]])
def power_delta_rule(mod, g, tmp): """ This rule is only used in tuning costs, so fine to skip for linked horizon's first timepoint. """ if check_if_first_timepoint( mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g] ) and (check_boundary_type(mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linear") or check_boundary_type(mod=mod, tmp=tmp, balancing_type=mod.balancing_type_project[g], boundary_type="linked")): pass else: return mod.GenHydroMustTake_Gross_Power_MW[g, tmp] \ - mod.GenHydroMustTake_Gross_Power_MW[g, mod.prev_tmp[ tmp, mod.balancing_type_project[g]]]