def test_flow_count_limit(self): """ """ bel = solph.Bus(label='electricityBus') solph.Source(label='source1', outputs={ bel: solph.Flow(nonconvex=solph.NonConvex(), nominal_value=100, emission_factor=[0.5, -1.0, 2.0]) }) solph.Source(label='source2', outputs={ bel: solph.Flow(nonconvex=solph.NonConvex(), nominal_value=100, emission_factor=3.5) }) # Should be ignored because emission_factor is not defined. solph.Source(label='source3', outputs={ bel: solph.Flow(nonconvex=solph.NonConvex(), nominal_value=100) }) # Should be ignored because it is not NonConvex. solph.Source(label='source4', outputs={ bel: solph.Flow(emission_factor=1.5, min=0.3, nominal_value=100) }) om = self.get_om() # one of the two flows has to be active solph.constraints.limit_active_flow_count_by_keyword(om, "emission_factor", lower_limit=1, upper_limit=2) self.compare_lp_files('flow_count_limit.lp', my_om=om)
def test_offsettransformer__too_many_input_flows(): """Too many Input Flows defined.""" with tools.assert_raises_regexp( ValueError, 'OffsetTransformer` must not have more than 1'): bgas = solph.Bus(label='GasBus') bcoal = solph.Bus(label='CoalBus') solph.components.OffsetTransformer( label='ostf_2_in', inputs={ bgas: solph.Flow( nominal_value=60, min=0.5, max=1.0, nonconvex=solph.NonConvex()), bcoal: solph.Flow( nominal_value=30, min=0.3, max=1.0, nonconvex=solph.NonConvex()) }, coefficients=(20, 0.5))
def test_flow_classes(): with assert_raises(ValueError): solph.Flow(fixed=True) with assert_raises(ValueError): solph.Flow(investment=solph.Investment(), nominal_value=4) with assert_raises(ValueError): solph.Flow(investment=solph.Investment(), nonconvex=solph.NonConvex()) with assert_raises(AttributeError): solph.Flow(fixed_costs=34)
def add_heatpipes_exist(pipes, labels, gd, q, b_in, b_out, nodes): """ Adds *HeatPipeline* objects with fix capacity for existing pipes to the list of oemof.solph components. Parameters ---------- pipes labels : dict Dictonary containing specifications for label-tuple. gd : dict Settings of the investment optimisation of the ThermalNetwork q : pd.Series Specific *Pipe* of ThermalNetwork b_in : oemof.solph.Bus Bus of Inflow b_out : oemof.solph.Bus Bus of Outflow nodes : list All oemof.solph components are added to the list Returns ------- list : Updated list of nodes. """ # get index of existing pipe label of pipe data ind_pipe = pipes[pipes['label_3'] == q['hp_type']].index[0] t = pipes.loc[ind_pipe] # get label of pipe labels['l_3'] = t['label_3'] hlf = t['l_factor'] * q['length'] hlff = t['l_factor_fix'] * q['length'] flow_bi_args = { 'bidirectional': True, 'min': -1} \ if gd['bidirectional_pipes'] else {} outflow_args = {'nonconvex': solph.NonConvex()} if t['nonconvex'] else {} nodes.append(oh.HeatPipeline( label=oh.Label(labels['l_1'], labels['l_2'], labels['l_3'], labels['l_4']), inputs={b_in: solph.Flow(**flow_bi_args)}, outputs={b_out: solph.Flow( nominal_value=q['capacity'], **flow_bi_args, **outflow_args, )}, heat_loss_factor=hlf, heat_loss_factor_fix=hlff, )) return nodes
def test_maximum_shutdowns(self): """Testing maximum_shutdowns attribute for nonconvex flows.""" bus_t = solph.Bus(label='Bus_C') solph.Source(label='cheap_plant_maximum_shutdowns', outputs={ bus_t: solph.Flow( nominal_value=10, min=0.5, max=1.0, variable_costs=10, nonconvex=solph.NonConvex(maximum_shutdowns=2)) }) self.compare_lp_files('maximum_shutdowns.lp')
def test_offsettransformer_too_many_output_flows(): """Too many Output Flows defined.""" with tools.assert_raises_regexp( ValueError, 'OffsetTransformer` must not have more than 1'): bm1 = solph.Bus(label='my_offset_Bus1') bm2 = solph.Bus(label='my_offset_Bus2') solph.components.OffsetTransformer( label='ostf_2_out', inputs={ bm1: solph.Flow( nominal_value=60, min=0.5, max=1.0, nonconvex=solph.NonConvex()) }, outputs={bm1: solph.Flow(), bm2: solph.Flow()}, coefficients=(20, 0.5))
def test_min_max_runtime(self): """Testing min and max runtimes for nonconvex flows.""" bus_t = solph.Bus(label='Bus_T') solph.Source(label='cheap_plant_min_down_constraints', outputs={ bus_t: solph.Flow(nominal_value=10, min=0.5, max=1.0, variable_costs=10, nonconvex=solph.NonConvex( minimum_downtime=4, minimum_uptime=2, initial_status=2, startup_costs=5, shutdown_costs=7)) }) self.compare_lp_files('min_max_runtime.lp')
def test_offsettransformer(self): """Constraint test of a OffsetTransformer. """ bgas = solph.Bus(label='gasBus') bth = solph.Bus(label='thermalBus') solph.components.OffsetTransformer(label='gasboiler', inputs={ bgas: solph.Flow( nonconvex=solph.NonConvex(), nominal_value=100, min=0.32, ) }, outputs={bth: solph.Flow()}, coefficients=[-17, 0.9]) self.compare_lp_files('offsettransformer.lp')
solph.Flow(fixed=True, actual_value=data['demand_el'], nominal_value=10) }) dummy_el = solph.Sink(label='dummy_el', inputs={bel: solph.Flow(variable_costs=10)}) pp1 = solph.Source(label='plant_min_down_constraints', outputs={ bel: solph.Flow(nominal_value=10, min=0.5, max=1.0, variable_costs=10, nonconvex=solph.NonConvex(minimum_downtime=4, initial_status=0)) }) pp2 = solph.Source(label='plant_min_up_constraints', outputs={ bel: solph.Flow(nominal_value=10, min=0.5, max=1.0, variable_costs=10, nonconvex=solph.NonConvex(minimum_uptime=2, initial_status=1)) }) # create an optimization problem and solve it om = solph.Model(es)
demand_el = solph.Sink(label='demand_el', inputs={bel: solph.Flow( variable_costs=data['price_el'])}) # combined cycle extraction turbine ccet = solph.components.GenericCHP( label='combined_cycle_extraction_turbine', fuel_input={bgas: solph.Flow( H_L_FG_share_max=[0.19 for p in range(0, periods)])}, electrical_output={bel: solph.Flow( nominal_value=200, min= 80/200, P_max_woDH=[200 for p in range(0, periods)], P_min_woDH=[80 for p in range(0, periods)], Eta_el_max_woDH=[0.53 for p in range(0, periods)], Eta_el_min_woDH=[0.43 for p in range(0, periods)], nonconvex=solph.NonConvex(startup_costs=5, shutdown_costs=5))}, heat_output={bth: solph.Flow( Q_CW_min=[30 for p in range(0, periods)])}, Beta=[0.19 for p in range(0, periods)], back_pressure=False) # create an optimization problem and solve it om = solph.Model(es) # debugging # om.write('generic_chp.lp', io_options={'symbolic_solver_labels': True}) # solve model om.solve(solver='cplex', solve_kwargs={'tee': True}) # create result object
def test_wrong_combination_of_options(): msg = "Investment flows cannot be combined with nonconvex flows!" with pytest.raises(ValueError, match=msg): solph.Flow(investment=solph.Investment(), nonconvex=solph.NonConvex())
def test_gen_ostf(): # read sequence data full_filename = os.path.join(os.path.dirname(__file__), 'ostf.csv') data = pd.read_csv(full_filename) # select periods periods = len(data) - 1 # create an energy system idx = pd.date_range('1/1/2017', periods=periods, freq='H') es = solph.EnergySystem(timeindex=idx) Node.registry = es # resources bgas = solph.Bus(label='bgas') solph.Source(label='rgas', outputs={bgas: solph.Flow()}) # heat bth = solph.Bus(label='bth') solph.Source(label='source_th', outputs={bth: solph.Flow(variable_costs=1000)}) solph.Sink(label='demand_th', inputs={ bth: solph.Flow(fixed=True, actual_value=data['demand_th'], nominal_value=200) }) # power bel = solph.Bus(label='bel') solph.Source(label='source_el', outputs={bel: solph.Flow(variable_costs=data['price_el'])}) # generic chp hp = solph.custom.OffsetTransformer( label='heat_pump', inputs={ bel: solph.Flow(nominal_value=100, max=[1 for i in range(0, periods)], min=[0.25 for i in range(0, periods)], nonconvex=solph.NonConvex()) }, outputs={bth: solph.Flow()}, coefficients=[[0 for i in range(0, periods)], [2 for i in range(0, periods)]]) # create an optimization problem and solve it om = solph.Model(es) # solve model om.solve(solver='cbc') # create result object results = processing.results(om) data = views.node(results, 'bth')['sequences'].sum(axis=0).to_dict() test_dict = { (('heat_pump', 'bth'), 'flow'): 18800.0, (('source_th', 'bth'), 'flow'): 1200.0, (('bth', 'demand_th'), 'flow'): 20000.0 } for key in test_dict.keys(): eq_(int(round(data[key])), int(round(test_dict[key])))
conversion_factors={bel: 0.5})) energysystem.add( Transformer(label='pp_gas', inputs={bgas: Flow()}, outputs={bel: Flow(nominal_value=41, variable_costs=40)}, conversion_factors={bel: 0.50})) energysystem.add( solph.custom.OffsetTransformer(label='ostf', inputs={ bgas: solph.Flow(nominal_value=60, min=0.5, max=1.0, nonconvex=solph.NonConvex()) }, outputs={bel: solph.Flow()}, coefficients={(bgas, bel): [20, 0.5]})) # create the model optimization_model = Model(energysystem) # solve problem optimization_model.solve(solver=solver, solve_kwargs={ 'tee': False, 'keepfiles': False }) meta_results = outputlib.processing.meta_results(optimization_model)
back_pressure=True) es_ref.add(bpt) # 30% m-Teillast bei 65-114°C und 50% m-Teillast bei 115-124°C if param.loc[('HP', 'active'), 'value'] == 1: hp = solph.components.OffsetTransformer( label='Wärmepumpe', inputs={ enw: solph.Flow(nominal_value=1, max=data['P_max_hp'], min=data['P_min_hp'], variable_costs=param.loc[('HP', 'op_cost_var'), 'value'], nonconvex=solph.NonConvex()) }, outputs={wnw: solph.Flow()}, coefficients=[data['c_0_hp'], data['c_1_hp']]) es_ref.add(hp) # %% Speicher # Saisonaler Speicher if param.loc[('TES', 'active'), 'value'] == 1: tes = solph.components.GenericStorage( label='Wärmespeicher', nominal_storage_capacity=param.loc[('TES', 'Q'), 'value'], inputs={ wnw:
def main(): """Execute main script.""" def invest_sol(A, col_type=''): """Pehnt et al. 2017, Markus [38]. A: Kollektorfläche der Solarthermie col_type: Kollektortyp der Solarthermie specific_coasts: Spezifische Kosten invest: Investitionskosten """ if col_type == 'flat': specific_costs = -34.06 * np.log(A) + 592.48 invest = A * specific_costs return invest elif col_type == 'vacuum': specific_costs = -40.63 * np.log(A) + 726.64 invest = A * specific_costs return invest else: raise ValueError( "Choose a valid collector type: 'flat' or 'vacuum'") def liste(parameter): """Get timeseries list of parameter for solph components.""" return [parameter for p in range(0, periods)] def result_labelling(dataframe): for col in dataframe.columns: if col in labeldict: dataframe.rename(columns={col: labeldict[col]}, inplace=True) else: print(col, ' not in labeldict') # %% Preprocessing # %% Daten einlesen dirpath = path.abspath(path.join(__file__, "../..")) filename = path.join(dirpath, 'Eingangsdaten\\simulation_data.csv') data = pd.read_csv(filename, sep=";") # filename = path.join(dirpath, 'Eingangsdaten\\All_parameters.csv') # param = pd.read_csv(filename, sep=";", index_col=['plant', 'parameter']) filepath = path.join(dirpath, 'Eingangsdaten\\parameter_v2b.json') with open(filepath, 'r') as file: param = json.load(file) # TODO cop_lt = 4.9501 A = param['Sol']['A'] invest_solar = invest_sol(A, col_type="flat") # %% Zeitreihe periods = len(data) date_time_index = pd.date_range('1/1/2016 00:00:00', periods=periods, freq='h') # %% Energiesystem erstellen es_ref = solph.EnergySystem(timeindex=date_time_index) # %% Wärmebedarf # rel_demand ist die Variable, die den Wärmebedarf der Region # prozentual von FL angibt. heat_demand_FL = data['heat_demand'] rel_heat_demand = 1 heat_demand_local = heat_demand_FL * rel_heat_demand total_heat_demand = float(heat_demand_local.sum()) # %% Energiesystem # %% LT-WNW Plausibilität prüfen if (param['LT-HP']['active'] and not param['Sol']['active'] and not param['TES']['active']): print("WARNING: You can't have the low temp heat pump active without ", "using either the TES or solar heat.") exit() elif (not param['LT-HP']['active'] and (param['Sol']['active'] or param['TES']['active'])): print( "WARNING: You can't use TES or solar heat without using the low ", "temp heat pump.") exit() # %% Busses gnw = solph.Bus(label='Gasnetzwerk') enw = solph.Bus(label='Elektrizitätsnetzwerk') wnw = solph.Bus(label='Wärmenetzwerk') lt_wnw = solph.Bus(label='LT-Wärmenetzwerk') es_ref.add(gnw, enw, wnw, lt_wnw) # %% Soruces gas_source = solph.Source( label='Gasquelle', outputs={ gnw: solph.Flow(variable_costs=(param['param']['gas_price'] + param['param']['co2_certificate'])) }) elec_source = solph.Source( label='Stromquelle', outputs={ enw: solph.Flow( variable_costs=(param['param']['elec_consumer_charges'] + data['el_spot_price'])) }) es_ref.add(gas_source, elec_source) if param['Sol']['active']: solar_source = solph.Source( label='Solarthermie', outputs={ lt_wnw: solph.Flow(variable_costs=(0.01 * invest_solar) / (A * data['solar_data'].sum()), nominal_value=(max(data['solar_data']) * A), actual_value=(data['solar_data']) / (max(data['solar_data'])), fixed=True) }) es_ref.add(solar_source) if param['MR']['active']: mr_source = solph.Source(label='Mustrun', outputs={ wnw: solph.Flow(variable_costs=0, nominal_value=float( param['MR']['Q_N']), actual_value=1) }) es_ref.add(mr_source) # %% Sinks elec_sink = solph.Sink( label='Spotmarkt', inputs={enw: solph.Flow(variable_costs=-data['el_spot_price'])}) heat_sink = solph.Sink( label='Wärmebedarf', inputs={ wnw: solph.Flow(variable_costs=-param['param']['heat_price'], nominal_value=max(heat_demand_local), actual_value=heat_demand_local / max(heat_demand_local), fixed=True) }) es_ref.add(elec_sink, heat_sink) if param['EC']['active']: ec_sink = solph.Sink(label='Emergency-cooling', inputs={wnw: solph.Flow(variable_costs=0)}) es_ref.add(ec_sink) # %% Transformer if param['EHK']['active']: for i in range(1, param['EHK']['amount'] + 1): ehk = solph.Transformer( label='Elektroheizkessel_' + str(i), inputs={enw: solph.Flow()}, outputs={ wnw: solph.Flow(nominal_value=param['EHK']['Q_N'], max=1, min=0, variable_costs=param['EHK']['op_cost_var']) }, conversion_factors={wnw: param['EHK']['eta']}) es_ref.add(ehk) if param['SLK']['active']: for i in range(1, param['SLK']['amount'] + 1): slk = solph.Transformer( label='Spitzenlastkessel_' + str(i), inputs={gnw: solph.Flow()}, outputs={ wnw: solph.Flow(nominal_value=param['SLK']['Q_N'], max=1, min=0, variable_costs=(param['SLK']['op_cost_var'] + param['param']['energy_tax'])) }, conversion_factors={wnw: param['SLK']['eta']}) es_ref.add(slk) if param['BHKW']['active']: for i in range(1, param['BHKW']['amount'] + 1): bhkw = solph.components.GenericCHP( label='BHKW_' + str(i), fuel_input={ gnw: solph.Flow(H_L_FG_share_max=liste( param['BHKW']['H_L_FG_share_max']), H_L_FG_share_min=liste( param['BHKW']['H_L_FG_share_min']), nominal_value=param['BHKW']['Q_in']) }, electrical_output={ enw: solph.Flow(variable_costs=param['BHKW']['op_cost_var'], P_max_woDH=liste(param['BHKW']['P_max_woDH']), P_min_woDH=liste(param['BHKW']['P_min_woDH']), Eta_el_max_woDH=liste( param['BHKW']['Eta_el_max_woDH']), Eta_el_min_woDH=liste( param['BHKW']['Eta_el_min_woDH'])) }, heat_output={ wnw: solph.Flow(Q_CW_min=liste(0), Q_CW_max=liste(0)) }, Beta=liste(0), back_pressure=False) es_ref.add(bhkw) if param['GuD']['active']: for i in range(1, param['GuD']['amount'] + 1): gud = solph.components.GenericCHP( label='GuD_' + str(i), fuel_input={ gnw: solph.Flow(H_L_FG_share_max=liste( param['GuD']['H_L_FG_share_max']), nominal_value=param['GuD']['Q_in']) }, electrical_output={ enw: solph.Flow( variable_costs=param['GuD']['op_cost_var'], P_max_woDH=liste(param['GuD']['P_max_woDH']), P_min_woDH=liste(param['GuD']['P_min_woDH']), Eta_el_max_woDH=liste(param['GuD']['Eta_el_max_woDH']), Eta_el_min_woDH=liste(param['GuD']['Eta_el_min_woDH'])) }, heat_output={ wnw: solph.Flow(Q_CW_min=liste(param['GuD']['Q_CW_min']), Q_CW_max=liste(0)) }, Beta=liste(param['GuD']['beta']), back_pressure=False) es_ref.add(gud) if param['BPT']['active']: for i in range(1, param['BPT']['amount'] + 1): bpt = solph.components.GenericCHP( label='bpt' + str(i), fuel_input={ gnw: solph.Flow(H_L_FG_share_max=liste( param['bpt']['H_L_FG_share_max']), nominal_value=param['bpt']['Q_in']) }, electrical_output={ enw: solph.Flow( variable_costs=param['bpt']['op_cost_var'], P_max_woDH=liste(param['bpt']['P_max_woDH']), P_min_woDH=liste(param['bpt']['P_min_woDH']), Eta_el_max_woDH=liste(param['bpt']['Eta_el_max_woDH']), Eta_el_min_woDH=liste(param['bpt']['Eta_el_min_woDH'])) }, heat_output={ wnw: solph.Flow(Q_CW_min=liste(0), Q_CW_max=liste(0)) }, Beta=liste(0), back_pressure=True) es_ref.add(bpt) # 30% m-Teillast bei 65-114°C und 50% m-Teillast bei 115-124°C if param['HP']['active']: for i in range(1, param['HP']['amount'] + 1): hp = solph.components.OffsetTransformer( label='HP_' + str(i), inputs={ enw: solph.Flow(nominal_value=1, max=data['P_max_hp'], min=data['P_min_hp'], variable_costs=param['HP']['op_cost_var'], nonconvex=solph.NonConvex()) }, outputs={wnw: solph.Flow()}, coefficients=[data['c_0_hp'], data['c_1_hp']]) es_ref.add(hp) # %% Speicher # Saisonaler Speicher if param['TES']['active']: for i in range(1, param['TES']['amount'] + 1): tes = solph.components.GenericStorage( label='TES_' + str(i), nominal_storage_capacity=param['TES']['Q'], inputs={ wnw: solph.Flow( storageflowlimit=True, nominal_value=param['TES']['Q_N_in'], max=param['TES']['Q_rel_in_max'], min=param['TES']['Q_rel_in_min'], variable_costs=param['TES']['op_cost_var'], nonconvex=solph.NonConvex( minimum_uptime=int(param['TES']['min_uptime']), initial_status=int(param['TES']['init_status']))) }, outputs={ lt_wnw: solph.Flow( storageflowlimit=True, nominal_value=param['TES']['Q_N_out'], max=param['TES']['Q_rel_out_max'], min=param['TES']['Q_rel_out_min'], nonconvex=solph.NonConvex( minimum_uptime=int(param['TES']['min_uptime']))) }, initial_storage_level=param['TES']['init_storage'], loss_rate=param['TES']['Q_rel_loss'], inflow_conversion_factor=param['TES']['inflow_conv'], outflow_conversion_factor=param['TES']['outflow_conv']) es_ref.add(tes) # Low temperature heat pump if param['LT-HP']['active']: for i in range(1, param['LT-HP']['amount'] + 1): lthp = solph.Transformer( label="LT-HP_" + str(i), inputs={ lt_wnw: solph.Flow(), enw: solph.Flow(variable_costs=param['HP']['op_cost_var']) }, outputs={wnw: solph.Flow()}, conversion_factors={ enw: 1 / data['cop_lthp'], lt_wnw: (data['cop_lthp'] - 1) / data['cop_lthp'] } # conversion_factors={enw: 1/cop_lt, # lt_wnw: (cop_lt-1)/cop_lt} ) es_ref.add(lthp) # %% Processing # %% Solve # Was bedeutet tee? model = solph.Model(es_ref) solph.constraints.limit_active_flow_count_by_keyword(model, 'storageflowlimit', lower_limit=0, upper_limit=1) # model.write('my_model.lp', io_options={'symbolic_solver_labels': True}) model.solve(solver='gurobi', solve_kwargs={'tee': True}, cmdline_options={"mipgap": "0.05"}) # %% Ergebnisse Energiesystem # Ergebnisse in results results = solph.processing.results(model) # Main- und Metaergebnisse es_ref.results['main'] = solph.processing.results(model) es_ref.results['meta'] = solph.processing.meta_results(model) invest_ges = 0 cost_Anlagen = 0 labeldict = {} # Busses data_gnw = views.node(results, 'Gasnetzwerk')['sequences'] data_enw = views.node(results, 'Elektrizitätsnetzwerk')['sequences'] data_wnw = views.node(results, 'Wärmenetzwerk')['sequences'] data_lt_wnw = views.node(results, 'LT-Wärmenetzwerk')['sequences'] labeldict[(('Gasquelle', 'Gasnetzwerk'), 'flow')] = 'H_source' labeldict[(('Elektrizitätsnetzwerk', 'Spotmarkt'), 'flow')] = 'P_spot_market' labeldict[(('Stromquelle', 'Elektrizitätsnetzwerk'), 'flow')] = 'P_source' labeldict[(('Wärmenetzwerk', 'Wärmebedarf'), 'flow')] = 'Q_demand' # Sources data_gas_source = views.node(results, 'Gasquelle')['sequences'] data_elec_source = views.node(results, 'Stromquelle')['sequences'] if param['Sol']['active']: data_solar_source = views.node(results, 'Solarthermie')['sequences'] invest_ges += invest_solar cost_Anlagen += (data_solar_source[( ('Solarthermie', 'LT-Wärmenetzwerk'), 'flow')].sum() * (0.01 * invest_solar) / (A * data['solar_data'].sum())) labeldict[(('Solarthermie', 'LT-Wärmenetzwerk'), 'flow')] = 'Q_Sol' if param['MR']['active']: data_mr_source = views.node(results, 'Mustrun')['sequences'] labeldict[(('Mustrun', 'Wärmenetzwerk'), 'flow')] = 'Q_MR' # Sinks data_elec_sink = views.node(results, 'Spotmarkt')['sequences'] data_heat_sink = views.node(results, 'Wärmebedarf')['sequences'] if param['EC']['active']: data_ec = views.node(results, 'Emergency-cooling')['sequences'] labeldict[(('Wärmenetzwerk', 'Emergency-cooling'), 'flow')] = 'Q_EC' # Transformer if param['EHK']['active']: invest_ges += (param['EHK']['inv_spez'] * param['EHK']['Q_N'] * param['EHK']['amount']) for i in range(1, param['EHK']['amount'] + 1): label_id = 'Elektroheizkessel_' + str(i) data_ehk = views.node(results, label_id)['sequences'] cost_Anlagen += ( data_ehk[((label_id, 'Wärmenetzwerk'), 'flow')].sum() * param['EHK']['op_cost_var'] + (param['EHK']['op_cost_fix'] * param['EHK']['Q_N'])) labeldict[((label_id, 'Wärmenetzwerk'), 'flow')] = 'Q_EHK_' + str(i) labeldict[(('Elektrizitätsnetzwerk', label_id), 'flow')] = 'P_zu_EHK_' + str(i) if param['SLK']['active']: invest_ges += (param['SLK']['inv_spez'] * param['SLK']['Q_N'] * param['SLK']['amount']) for i in range(1, param['SLK']['amount'] + 1): label_id = 'Spitzenlastkessel_' + str(i) data_slk = views.node(results, label_id)['sequences'] cost_Anlagen += ( data_slk[((label_id, 'Wärmenetzwerk'), 'flow')].sum() * (param['SLK']['op_cost_var'] + param['param']['energy_tax']) + (param['SLK']['op_cost_fix'] * param['SLK']['Q_N'])) labeldict[((label_id, 'Wärmenetzwerk'), 'flow')] = 'Q_SLK_' + str(i) labeldict[(('Gasnetzwerk', label_id), 'flow')] = 'H_SLK_' + str(i) if param['BHKW']['active']: invest_ges += (param['BHKW']['P_max_woDH'] * param['BHKW']['inv_spez'] * param['BHKW']['amount']) for i in range(1, param['BHKW']['amount'] + 1): label_id = 'BHKW_' + str(i) data_bhkw = views.node(results, label_id)['sequences'] cost_Anlagen += ( data_bhkw[( (label_id, 'Elektrizitätsnetzwerk'), 'flow')].sum() * param['BHKW']['op_cost_var'] + (param['BHKW']['op_cost_fix'] * param['BHKW']['P_max_woDH'])) labeldict[((label_id, 'Wärmenetzwerk'), 'flow')] = 'Q_' + label_id labeldict[((label_id, 'Elektrizitätsnetzwerk'), 'flow')] = 'P_' + label_id labeldict[(('Gasnetzwerk', label_id), 'flow')] = 'H_' + label_id if param['GuD']['active']: invest_ges += (param['GuD']['P_max_woDH'] * param['GuD']['inv_spez'] * param['GuD']['amount']) for i in range(1, param['GuD']['amount'] + 1): label_id = 'GuD_' + str(i) data_gud = views.node(results, label_id)['sequences'] cost_Anlagen += ( data_gud[((label_id, 'Elektrizitätsnetzwerk'), 'flow')].sum() * param['GuD']['op_cost_var'] + (param['GuD']['op_cost_fix'] * param['GuD']['P_max_woDH'])) labeldict[((label_id, 'Wärmenetzwerk'), 'flow')] = 'Q_' + label_id labeldict[((label_id, 'Elektrizitätsnetzwerk'), 'flow')] = 'P_' + label_id labeldict[(('Gasnetzwerk', label_id), 'flow')] = 'H_' + label_id if param['HP']['active']: invest_ges += (param['HP']['inv_spez'] * data['P_max_hp'].max() * param['HP']['amount']) for i in range(1, param['HP']['amount'] + 1): label_id = 'HP_' + str(i) data_hp = views.node(results, label_id)['sequences'] cost_Anlagen += ( data_hp[(('Elektrizitätsnetzwerk', label_id), 'flow')].sum() * param['HP']['op_cost_var'] + (param['HP']['op_cost_fix'] * data['P_max_hp'].max())) labeldict[((label_id, 'Wärmenetzwerk'), 'flow')] = 'Q_ab_' + label_id labeldict[(('Elektrizitätsnetzwerk', label_id), 'flow')] = 'P_zu_' + label_id labeldict[(('Elektrizitätsnetzwerk', label_id), 'status')] = 'Status_' + label_id if param['LT-HP']['active']: for i in range(1, param['LT-HP']['amount'] + 1): label_id = 'LT-HP_' + str(i) data_lt_hp = views.node(results, label_id)['sequences'] invest_ges += (param['HP']['inv_spez'] * data_wnw[( (label_id, 'Wärmenetzwerk'), 'flow')].max() / data['cop_lthp'].mean()) cost_Anlagen += (data_lt_hp[( ('Elektrizitätsnetzwerk', label_id), 'flow')].sum() * param['HP']['op_cost_var'] + (param['HP']['op_cost_fix'] * data_wnw[( (label_id, 'Wärmenetzwerk'), 'flow')].max() / data['cop_lthp'].mean())) labeldict[((label_id, 'Wärmenetzwerk'), 'flow')] = 'Q_ab_' + label_id labeldict[(('Elektrizitätsnetzwerk', label_id), 'flow')] = 'P_zu_' + label_id labeldict[(('LT-Wärmenetzwerk', label_id), 'flow')] = 'Q_zu_' + label_id # Speicher if param['TES']['active']: invest_ges += (param['TES']['inv_spez'] * param['TES']['Q'] * param['TES']['amount']) for i in range(1, param['TES']['amount'] + 1): label_id = 'TES_' + str(i) data_tes = views.node(results, label_id)['sequences'] cost_Anlagen += (data_tes[( ('Wärmenetzwerk', label_id), 'flow')].sum() * param['TES']['op_cost_var'] + (param['TES']['op_cost_fix'] * param['TES']['Q'])) labeldict[((label_id, 'LT-Wärmenetzwerk'), 'flow')] = 'Q_ab_' + label_id labeldict[((label_id, 'LT-Wärmenetzwerk'), 'status')] = 'Status_ab_' + label_id labeldict[(('Wärmenetzwerk', label_id), 'flow')] = 'Q_zu_' + label_id labeldict[(('Wärmenetzwerk', label_id), 'status')] = 'Status_zu_' + label_id labeldict[((label_id, 'None'), 'storage_content')] = 'Speicherstand_' + label_id # %% Zahlungsströme Ergebnis objective = abs(es_ref.results['meta']['objective']) # %% Geldflüsse # # Primärenergiebezugskoste cost_gas = ( data_gnw[(('Gasquelle', 'Gasnetzwerk'), 'flow')].sum() * (param['param']['gas_price'] + param['param']['co2_certificate'])) el_flow = np.array(data_enw[(('Stromquelle', 'Elektrizitätsnetzwerk'), 'flow')]) cost_el_timeseries = np.array(data['el_price']) cost_el_array = el_flow * cost_el_timeseries cost_el = cost_el_array.sum() # Erlöse revenues_spotmarkt_timeseries = (np.array(data_enw[( ('Elektrizitätsnetzwerk', 'Spotmarkt'), 'flow')]) * np.array(data['el_spot_price'])) revenues_spotmarkt = revenues_spotmarkt_timeseries.sum() revenues_heatdemand = (data_wnw[( ('Wärmenetzwerk', 'Wärmebedarf'), 'flow')].sum() * param['param']['heat_price']) # Summe der Geldströme Gesamtbetrag = (revenues_spotmarkt + revenues_heatdemand - cost_Anlagen - cost_gas - cost_el) # %% Output Ergebnisse # Umbenennen der Spaltennamen der Ergebnisdataframes result_dfs = [data_wnw, data_lt_wnw, data_tes, data_enw, data_gnw] for df in result_dfs: result_labelling(df) # Daten zum Plotten der Wärmeversorgung df1 = pd.concat([data_wnw, data_lt_wnw, data_tes, data_enw], axis=1) df1.to_csv(path.join(dirpath, 'Ergebnisse\\Vorarbeit\\Vor_wnw.csv'), sep=";") # Daten zum Plotten der Investitionsrechnung df2 = pd.DataFrame( data={ 'invest_ges': [invest_ges], 'Q_tes': [param['TES']['Q']], 'total_heat_demand': [total_heat_demand], 'Gesamtbetrag': [Gesamtbetrag] }) df2.to_csv(path.join(dirpath, 'Ergebnisse\\Vorarbeit\\Vor_Invest.csv'), sep=";") # Daten für die ökologische Bewertung df3 = pd.concat( [data_gnw[['H_source']], data_enw[['P_spot_market', 'P_source']]], axis=1) df3.to_csv(path.join(dirpath, 'Ergebnisse\\Vorarbeit\\Vor_CO2.csv'), sep=";")
es_ref.add(ehk, slk, bhkw) # %% Speicher # Saisonaler Speicher tes = solph.components.GenericStorage( label='Wärmespeicher', nominal_storage_capacity=Q_tes, inputs={ wnw: solph.Flow(nominal_value=nom_heat_demand_local / 4, max=1, min=0.1, variable_costs=op_cost_tes, nonconvex=solph.NonConvex(minimum_uptime=3, initial_status=0)) }, outputs={ wnw: solph.Flow(nominal_value=nom_heat_demand_local / 4, max=1, min=0.1, nonconvex=solph.NonConvex(minimum_uptime=3, initial_status=0)) }, initial_storage_level=0.7, inflow_conversion_factor=1, outflow_conversion_factor=0.75) es_ref.add(tes)
es = solph.EnergySystem(timeindex=time) b_heat = solph.Bus(label='b_heat') es.add(b_heat) sink_heat = solph.Sink( label='demand', inputs={b_heat: solph.Flow(fix=demand_heat, nominal_value=1)}) fireplace = solph.Source( label='fireplace', outputs={b_heat: solph.Flow(nominal_value=3, variable_costs=0, nonconvex=solph.NonConvex( activity_costs=activity_costs))}) boiler = solph.Source( label='boiler', outputs={b_heat: solph.Flow(nominal_value=10, variable_costs=1)}) es.add(sink_heat, fireplace, boiler) ########################################################################## # Optimise the energy system ########################################################################## # create an optimization problem and solve it om = solph.Model(es)
def ht_heat_pump(param, data, busses): r""" Get high temperature heat pump for Generic Model energy system. Parameters ---------- param : dict JSON parameter file of user defined constants. data : pandas.DataFrame csv file of user defined time dependent parameters. busses : dict of solph.Bus Busses of the energy system. Note ---- High temperature heat pump uses the following parameters: - 'active' is a binary parameter wether is used or not - 'type' defines wether it is used constant or time dependent - 'amount' is the amount of this components installed - 'P_max' is the constant maximum output power in MW - 'P_min' is the constant minimum output power in MW - 'c_1' is the linear coefficicient 1 (slope) - 'c_0' is the linear coefficicient 0 (y-intersection) - 'P_max_hp' is the time series of maximum output power in MW - 'P_min_hp' is the time series minimum output power in MW - 'elec_consumer_charges_self' are the constant consumer charges for internal electricity usage in €/MWh - 'op_cost_var' are the variable operational costs in €/MWh Topology -------- Input: Electricity network (enw) Output: High temperature heat network (wnw) """ if param['HP']['active']: if param['HP']['type'] == 'constant': for i in range(1, param['HP']['amount'] + 1): ht_hp = solph.components.OffsetTransformer( label='HP_' + str(i), inputs={ busses['enw']: solph.Flow( nominal_value=param['HP']['P_max'], max=1, min=param['HP']['P_min'] / param['HP']['P_max'], variable_costs=( param['param']['elec_consumer_charges_self']), nonconvex=solph.NonConvex()) }, outputs={ busses['wnw']: solph.Flow(variable_costs=param['HP']['op_cost_var']) }, coefficients=[param['HP']['c_0'], param['HP']['c_1']]) return ht_hp elif param['HP']['type'] == 'time series': for i in range(1, param['HP']['amount'] + 1): ht_hp = solph.components.OffsetTransformer( label='HP_' + str(i), inputs={ busses['enw']: solph.Flow( nominal_value=1, max=data['P_max_hp'], min=data['P_min_hp'], variable_costs=( param['param']['elec_consumer_charges_self']), nonconvex=solph.NonConvex()) }, outputs={ busses['wnw']: solph.Flow(variable_costs=param['HP']['op_cost_var']) }, coefficients=[data['c_0_hp'], data['c_1_hp']]) return ht_hp else: raise ComponentTypeError(param['HP']['type'], 'HP')
def short_term_thermal_energy_storage(param, busses): r""" Get short term thermal energy storage for Generic Model energy system. Parameters ---------- param : dict JSON parameter file of user defined constants. busses : dict of solph.Bus Busses of the energy system. Note ---- Short term thermal energy storage uses the following parameters: - 'active' is a binary parameter wether is used or not - 'amount' is the amount of this components installed - 'Q_N_in' is the constant nominal input value in MWh - 'Q_N_out' is the constant nominal output value in MWh - 'Q_rel_in_max' is a scaling factor for maximal heat input - 'Q_rel_in_min' is a scaling factor for minimal heat input - 'Q_rel_out_max' is a scaling factor for maximal heat output - 'Q_rel_out_min' is a scaling factor for minimal heat output - 'min_uptime' is the amount of time steps the storage has to be on during operation - 'init_status' is the value wheter the state of charge is active at the beginning - 'init_storage' is the start value of the state of charge - 'balanced' is the condition whether the state of charge at the end of the optimiziation period is the same as at the beginning - 'Q_rel_loss' is the constant loss rate to environment - 'inflow_conv' is the constant inflow conversion factor - 'outflow_conv' is the constant outflow conversion factor - 'op_cost_var' are the variable operational costs in €/MWh Topology -------- Input: High temperature heat network (wnw) Output: High temperature heat network (wnw) """ if param['ST-TES']['active']: for i in range(1, param['ST-TES']['amount'] + 1): st_tes = solph.components.GenericStorage( label='ST-TES_' + str(i), nominal_storage_capacity=param['ST-TES']['Q'], inputs={ busses['wnw']: solph.Flow(storageflowlimit=True, nominal_value=param['ST-TES']['Q_N_in'], max=param['ST-TES']['Q_rel_in_max'], min=param['ST-TES']['Q_rel_in_min'], variable_costs=param['ST-TES']['op_cost_var'], nonconvex=solph.NonConvex(initial_status=int( param['ST-TES']['init_status']))) }, outputs={ busses['wnw']: solph.Flow(storageflowlimit=True, nominal_value=param['ST-TES']['Q_N_out'], max=param['ST-TES']['Q_rel_out_max'], min=param['ST-TES']['Q_rel_out_min'], nonconvex=solph.NonConvex()) }, initial_storage_level=param['ST-TES']['init_storage'], loss_rate=param['ST-TES']['Q_rel_loss'], inflow_conversion_factor=param['ST-TES']['inflow_conv'], outflow_conversion_factor=param['ST-TES']['outflow_conv']) return st_tes
actual_value=[ heat_demand(day) for day in range(0, periods) ], nominal_value=10) }) fireplace = solph.Source(label='fireplace', outputs={ b_heat: solph.Flow( nominal_value=10, min=0.4, max=1.0, variable_costs=0.1, nonconvex=solph.NonConvex(minimum_uptime=2, initial_status=1)) }) boiler = solph.Source( label='boiler', outputs={b_heat: solph.Flow(nominal_value=10, variable_costs=0.2)}) # basic model for solar thermal yield, solely based on the day of the year def solar_thermal(d): return 0.5 - 0.5 * np.cos(2 * np.pi * d / 356) # For one year, the equivalent periodical costs (epc) of an # investment are equal to the annuity. epc = economics.annuity(5000, 20, 0.05)
bel = solph.Bus(label='bel') # There are a sink and a source, both creating a revenue (negative cost), # so it would be optimal to use both at the same time. To suppress this, # the constraint "limit_active_flow_count" is used. # You might define any keyword (here "my_keyword") like: # > Flow(nonconvex=solph.NonConvex(), # > my_keyword=True, # ...) # But also any existing one (e.g. "emission_factor") can be used. solph.Source(label='source1', outputs={ bel: solph.Flow(nonconvex=solph.NonConvex(), nominal_value=210, variable_costs=[-1, -5, -1, -1], max=[1, 1, 1, 0], my_keyword=True) }) # Note: The keyword is also defined when set to False. solph.Sink(label='sink1', inputs={ bel: solph.Flow(nonconvex=solph.NonConvex(), variable_costs=[-2, -1, -2, -2], nominal_value=250, max=[1, 1, 1, 0], my_keyword=False)