def supply_rule(self, sy, nd, ca): ''' Balance supply/demand ''' list_neg = self.sll | self.curt prod = (# power output; negative if energy selling plant sum(self.pwr[sy, pp, ca] * (-1 if pp in list_neg else 1) for (pp, nd, ca) in set_to_list(self.ppall_ndca, [None, nd, ca])) # incoming inter-node transmission + sum(get_transmission(sy, nd, nd_2, ca, False) / self.nd_weight[nd_2] for (nd, nd_2, ca) in set_to_list(self.ndcnn, [None, nd, ca])) ) exports = sum(get_transmission(sy, nd, nd_2, ca, True) / self.nd_weight[nd] for (nd, nd_2, ca) in set_to_list(self.ndcnn, [nd, None, ca])) dmnd = (self.dmnd[sy, nd, ca] + sum(self.pwr_st_ch[sy, st, ca] for (st, nd, ca) in set_to_list(self.st_ndca, [None, nd, ca]))) # demand of plants using ca as an input ca_cons = (po.ZeroConstant if not self.pp_ndcaca else sum(self.pwr[sy, pp, ca_out] / self.pp_eff[pp, ca_out] for (pp, nd, ca_out, ca) in set_to_list(self.pp_ndcaca, [None, nd, None, ca]))) gl = self.grid_losses[nd, ca] return prod == (dmnd + ca_cons) * (1 + gl) + exports
def get_vc_fl(self): r''' Get total fuel cost calculated directly from power production: .. math:: \sum_\mathrm{(t,p,c)\in sy\_lin\_ca} p_\mathrm{t,p,c} w_\mathrm{\tau(p),t} \cdot \mathrm{vc_{f(p),n(p)}} \cdot (f_\mathrm{0,p,c} + 0.5 p_\mathrm{t,p,c} f_\mathrm{1,p,c}) ''' def spec_vc_fl(lin, sy): fl_id, nd_id = (self.mps.dict_plant_2_fuel_id[lin], self.mps.dict_plant_2_node_id[lin]) if self.dict_par['vc_fl'].has_monthly_factors: mt_id = self.dict_soy_month[(self.dict_pp_tm_id[lin], sy)] return self.vc_fl[mt_id, fl_id, nd_id] else: return self.vc_fl[fl_id, nd_id] return \ sum(self.pwr[sy, lin, ca] * self.weight[self.dict_pp_tm_id[lin], sy] * spec_vc_fl(lin, sy) * (self.factor_lin_0[lin, ca] + 0.5 * self.pwr[sy, lin, ca] * self.factor_lin_1[lin, ca]) * self.nd_weight[self.mps.dict_plant_2_node_id[lin]] for (sy, lin, ca) in set_to_list(self.sy_lin_ca, nnn))
def yearly_energy_rule(self, pp, ca): ''' Sets variable erg_yr for fuel-consuming plants. ''' tm = self.dict_pp_tm_id[pp] return (self.erg_yr[pp, ca] == sum(self.pwr[sy, pp, ca] * self.weight[tm, sy] for tm, sy in set_to_list(self.tmsy, [tm, None])))
def yearly_ramp_rule(self, pp, ca): ''' Yearly ramping in MW/yrm, absolute aggregated up and down. ''' tm = self.dict_pp_tm_id[pp] tmsy_list = set_to_list(self.tmsy, [tm, None]) return (self.pwr_ramp_yr[pp, ca] == sum(self.pwr_ramp_abs[sy, pp, ca] for tm, sy in tmsy_list))
def calc_vc_fl_pp_rule(self, pp, nd, ca, fl): '''Yearly fuel cost calculation (constant supply curve plants).''' tm = self.dict_nd_tm_id[nd] list_sy = self.dict_tm_sy[tm] sign = -1 if pp in self.sll else 1 # Case 1: fuel has price profile if (fl, nd, ca) in {**self.dict_pricebuy_pf, **self.dict_pricesll_pf}: pprf = (self.pricesllprof if sign is -1 else self.pricebuyprof) pf = (self.dict_pricesll_pf[(fl, nd, ca)] if sign is -1 else self.dict_pricebuy_pf[(fl, nd, ca)]) sums = (sign * sum(self.weight[tm, sy] * pprf[sy, pf] / self.pp_eff[pp, ca] * self.pwr[sy, pp, ca] for (sy, _, _) in set_to_list(self.sy_pp_ca, [None, pp, ca]))) # Case 2: monthly adjustment factors have been applied to vc_fl elif self.dict_par['vc_fl'].has_monthly_factors: sums = (sign * sum(self.weight[tm, sy] * self.vc_fl[self.dict_soy_month[(tm, sy)], fl, nd] / self.pp_eff[pp, ca] * self.pwr[sy, pp, ca] for (sy, _pp, _ca) in set_to_list(self.sy_pp_ca, [None, pp, ca]))) # Case 3: ordinary single fuel price else: sums = (sign * self.erg_fl_yr[pp, nd, ca, fl] / self.pp_eff[pp, ca] * self.vc_fl[fl, nd]) return self.vc_fl_pp_yr[pp, ca, fl] == sums
def objective_rule_quad(self): return (# FUEL COST CONSTANT sum(self.vc_fl_pp_yr[pp, ca, fl] * self.nd_weight[self.mps.dict_plant_2_node_id[pp]] for (pp, ca, fl) in set_to_list(self.pp_cafl - self.lin_cafl, nnn)) # FUEL COST LINEAR + self.get_vc_fl() # EMISSION COST LINEAR + self.get_vc_co() + sum(self.vc_co2_pp_yr[pp, ca] * self.nd_weight[self.mps.dict_plant_2_node_id[pp]] for (pp, ca) in set_to_list(self.pp_ca - self.lin_ca, nn)) + sum(self.vc_om_pp_yr[pp, ca] * self.nd_weight[self.mps.dict_plant_2_node_id[pp]] for (pp, ca) in set_to_list(self.ppall_ca, nn)) + sum(self.vc_ramp_yr[pp, ca] * self.nd_weight[self.mps.dict_plant_2_node_id[pp]] for (pp, ca) in set_to_list(self.rp_ca, nn)) + sum(self.fc_om_pp_yr[pp, ca] * self.nd_weight[self.mps.dict_plant_2_node_id[pp]] for (pp, ca) in set_to_list(self.ppall_ca, nn)) + sum(self.fc_cp_pp_yr[pp, ca] * self.nd_weight[self.mps.dict_plant_2_node_id[pp]] for (pp, ca) in set_to_list(self.add_ca, nn)))
def calc_vc_co2_pp_rule(self, pp, nd, ca, fl): '''Yearly emission ncost calculation (constant supply curves).''' tm = self.dict_nd_tm_id[nd] # Case 1: monthly adjustment factors have been applied to vc_fl if self.dict_par['price_co2'].has_monthly_factors: sums = sum(self.pwr[sy, pp, ca] # POWER! / self.pp_eff[pp, ca] * self.weight[tm, sy] * self.price_co2[mt, nd] * self.co2_int[fl] for (_tm, sy, mt) in set_to_list(self.tmsy_mt, [tm, None, None])) # Case 2: ordinary single CO2 price else: sums = (self.erg_fl_yr[pp, nd, ca, fl] # ENERGY! / self.pp_eff[pp, ca] * self.price_co2[nd] * self.co2_int[fl]) return self.vc_co2_pp_yr[pp, ca] == sums
def pp_max_fuel_rule(self, nd, ca, fl): '''Constrain energy produced from certain fuels.''' is_constr = fl in self.fl_erg erg_inp_is_zero = self.erg_inp[nd, ca, fl] == 0 ret = po.Constraint.Skip if is_constr and not erg_inp_is_zero: plant_list = set_to_list(self.ppall_ndcafl, [None, nd, ca, fl]) if plant_list: left = sum(self.erg_fl_yr[pp, nd_1, ca_1, fl_1] for (pp, nd_1, ca_1, fl_1) in plant_list) right = self.erg_inp[nd, ca, fl] ret = left <= right return ret
def get_vc_co(self): r''' Get total |CO2| emission cost calculated directly from power production: .. math:: \sum_\mathrm{(t,p,c)\in sy\_lin\_ca} p_\mathrm{t,p,c} w_\mathrm{\tau(p),t} \cdot \pi_\mathrm{CO_2, m(t), n(p)} i_\mathrm{CO_2,f} \cdot (f_\mathrm{0,p,c} + 0.5 p_\mathrm{t,p,c} f_\mathrm{1,p,c}) ''' return \ sum(self.pwr[sy, lin, ca] * self.weight[self.dict_pp_tm_id[lin], sy] * (self.price_co2[self.dict_soy_month[(self.dict_pp_tm_id[lin], sy)], self.mps.dict_plant_2_node_id[lin]] if self.dict_par['price_co2'].has_monthly_factors else self.price_co2[self.mps.dict_plant_2_node_id[lin]]) * self.co2_int[self.mps.dict_plant_2_fuel_id[lin]] * (self.factor_lin_0[lin, ca] + 0.5 * self.pwr[sy, lin, ca] * self.factor_lin_1[lin, ca]) * self.nd_weight[self.mps.dict_plant_2_node_id[lin]] for (sy, lin, ca) in set_to_list(self.sy_lin_ca, nnn))
def add_parameters(self): ''' Adds all parameters to the model. Generates :class:`ParameterAdder` instances for each of the parameters and calls their :meth:`ParameterAdder.init_update` method. ''' if __name__ == '__main__': self = ml.m list_par = ( Par('dmnd', self.sy_ndca, self._get_df_demand(), 'value'), Par('supprof', self.sy_pr_ca, self._get_df_supply(), 'value'), Par('chpprof', (self.sy_ndca), 'df_profchp_soy', 'value'), Par('inflowprof', (self.sy_hyrs_ca | self.sy_ror_ca), 'df_profinflow_soy', 'value', index_cols=['sy', 'pp_id', 'ca_id']), Par('pricebuyprof', (self.sy, self.pricebuy_pf), 'df_profpricebuy_soy', 'value'), Par('pricesllprof', (self.sy, self.pricesll_pf), 'df_profpricesll_soy', 'value'), Par('min_erg_mt_out_share', self.hyrs, 'df_hydro'), Par('max_erg_mt_in_share', self.hyrs, 'df_hydro', default=1), Par('min_erg_share', self.hyrs, 'df_hydro'), Par('weight', self.tmsy, 'df_tm_soy', default=1), Par('grid_losses', (self.nd, self.ca), 'df_node_encar'), Par('cap_trme_leg', (self.mt, self.ndcnn), 'df_node_connect'), Par('cap_trmi_leg', (self.mt, self.ndcnn), 'df_node_connect'), Par('vc_ramp', (self.ppall, self.ca), 'df_plant_encar', None, ['pp_id', 'ca_id'], set_to_list(self.rp_ca, [None, None])), Par('pp_eff', (self.pp - self.lin, self.ca), 'df_plant_encar', None, ['pp_id'], self.pp - self.lin, default=1), Par('cf_max', (self.pp, self.ca), 'df_plant_encar', None, ['pp_id'], self.pp), Par('erg_chp', (self.chp, self.ca), 'df_plant_encar', None, ['pp_id'], self.chp), Par('erg_inp', self.ndcafl, 'df_fuel_node_encar'), Par('vc_fl', (self.fl, self.nd), 'df_fuel_node_encar', default=0), Par('factor_lin_0', (self.lin, self.ca), 'df_plant_encar', None, ['pp_id'], self.lin, default=0), Par('factor_lin_1', (self.lin, self.ca), 'df_plant_encar', None, ['pp_id'], self.lin, default=0), Par('price_co2', self.nd, 'df_def_node'), Par('nd_weight', self.nd, 'df_def_node', default=1), Par('co2_int', self.fl, 'df_def_fuel', default=0), Par('cap_pwr_leg', (self.ppall_ca), 'df_plant_encar', None, ['pp_id'], self.ppall, index_cols=['pp_id', 'ca_id']), Par('vc_om', (self.ppall, self.ca), 'df_plant_encar', None, ['pp_id'], self.ppall), Par('fc_om', (self.add, self.ca), 'df_plant_encar', None, ['pp_id'], self.add, default=0), Par('fc_cp_ann', (self.add, self.ca), 'df_plant_encar', None, ['pp_id'], self.add), Par('pwr_pot', (self.add, self.ca), 'df_plant_encar', None, ['pp_id'], self.add, default=1e9), Par('cap_avlb', (self.pp, self.ca), 'df_plant_encar', None, ['pp_id'], self.pp, default=1), Par('st_lss_hr', (self.st, self.ca), 'df_plant_encar', None, ['pp_id'], self.st), Par('st_lss_rt', (self.st, self.ca), 'df_plant_encar', None, ['pp_id'], self.st), Par('discharge_duration', (self.st | self.hyrs, self.ca), 'df_plant_encar', None, ['pp_id'], self.st | self.hyrs), Par('hyd_erg_bc', (self.sy_hydbc, self.hyrs), 'df_plant_month'), ) self.dict_par = {} for par in list_par: parameter = ParameterAdder(self, par) self.dict_par[par.parameter_name] = parameter parameter.init_update()