def test_parameter_with_node_view(self): param_results = processing.parameter_as_dict(self.es, exclude_none=True) bel1 = views.node(param_results, 'b_el1') eq_(bel1['scalars'][(('b_el1', 'storage'), 'variable_costs')], 3) bel1_m = views.node(param_results, 'b_el1', multiindex=True) eq_(bel1_m['scalars'].loc[('b_el1', 'storage', 'variable_costs')], 3)
def update_flows(self, results, comp_name=None): """Updates the flows of a component for each time step. :param results: The oemof results for the given time step :type results: object :param comp_name: The name of the component - while components can generate more than one oemof model, they sometimes need to give a custom name, defaults to None :type comp_name: str, optional :return: updated flow values for each flow in the 'flows' dict """ # Check if the component has an attribute 'flows', if not, create it as an empty dict. if not hasattr(self, 'flows'): self.flows = {} if comp_name is None: comp_name = self.name this_comp_node = views.node(results, comp_name) this_df = this_comp_node['sequences'] for i_result in this_df: # Check if this result is a flow if i_result[1] == 'flow': this_flow_name = i_result[0][:] # Check if there already is an array to store the flow # information, if not, create one. if this_flow_name not in self.flows: self.flows[this_flow_name] = [ None ] * self.sim_params.n_intervals # Saving this flow value to the results file self.flows[this_flow_name][ self.sim_params.i_interval] = this_df[i_result][0]
def test_results_with_old_dump(): """ Test again with a stored dump created with v0.3.2dev (896a6d50) """ energysystem = solph.EnergySystem() energysystem.restore(dpath=os.path.dirname(os.path.realpath(__file__)), filename='es_dump_test_3_2dev.oemof') results = energysystem.results['main'] electricity_bus = views.node(results, 'electricity') my_results = electricity_bus['sequences'].sum(axis=0).to_dict() storage = energysystem.groups['storage'] my_results['storage_invest'] = results[(storage, None)]['scalars']['invest'] stor_invest_dict = { 'storage_invest': 2040000, (('electricity', 'demand'), 'flow'): 105867395, (('electricity', 'excess_bel'), 'flow'): 211771291, (('electricity', 'storage'), 'flow'): 2350931, (('pp_gas', 'electricity'), 'flow'): 5148414, (('pv', 'electricity'), 'flow'): 7488607, (('storage', 'electricity'), 'flow'): 1880745, (('wind', 'electricity'), 'flow'): 305471851 } for key in stor_invest_dict.keys(): eq_(int(round(my_results[key])), int(round(stor_invest_dict[key])))
def test_output_by_type_view(self): results = processing.results(self.om) transformer_output = views.node_output_by_type(results, node_type=Transformer) compare = views.node(results, 'diesel', multiindex=True)['sequences'][('diesel', 'b_el1', 'flow')] eq_(int(transformer_output.sum()), int(compare.sum()))
def test_net_storage_flow(self): results = processing.results(self.om) storage_flow = views.net_storage_flow(results, node_type=GenericStorage) compare = views.node(results, 'storage', multiindex=True)['sequences'] eq_(((compare[('storage', 'b_el2', 'flow')] - compare[('b_el1', 'storage', 'flow')]).to_frame() == storage_flow.values).all()[0], True)
def test_results_with_actual_dump(): energysystem = solph.EnergySystem() energysystem.restore() # Results results = energysystem.results['main'] meta = energysystem.results['meta'] electricity_bus = views.node(results, 'electricity') my_results = electricity_bus['sequences'].sum(axis=0).to_dict() storage = energysystem.groups['storage'] my_results['storage_invest'] = results[(storage, None)]['scalars']['invest'] stor_invest_dict = { 'storage_invest': 2040000, (('electricity', 'None'), 'duals'): 10800000000321, (('electricity', 'demand'), 'flow'): 105867395, (('electricity', 'excess_bel'), 'flow'): 211771291, (('electricity', 'storage'), 'flow'): 2350931, (('pp_gas', 'electricity'), 'flow'): 5148414, (('pv', 'electricity'), 'flow'): 7488607, (('storage', 'electricity'), 'flow'): 1880745, (('wind', 'electricity'), 'flow'): 305471851 } for key in stor_invest_dict.keys(): eq_(int(round(my_results[key])), int(round(stor_invest_dict[key]))) # Solver results eq_(str(meta['solver']['Termination condition']), 'optimal') eq_(meta['solver']['Error rc'], 0) eq_(str(meta['solver']['Status']), 'ok') # Problem results eq_(meta['problem']['Lower bound'], 4.231675777e+17) eq_(meta['problem']['Upper bound'], 4.231675777e+17) eq_(meta['problem']['Number of variables'], 2805) eq_(meta['problem']['Number of constraints'], 2806) eq_(meta['problem']['Number of nonzeros'], 1197) eq_(meta['problem']['Number of objectives'], 1) eq_(str(meta['problem']['Sense']), 'minimize') # Objective function eq_(round(meta['objective']), 423167578261115584)
def test_regression_investment_storage(solver='cbc'): """The problem was infeasible if the existing capacity and the maximum was defined in the Flow. """ logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=4, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) Node.registry = energysystem # Buses bgas = solph.Bus(label=('natural', 'gas')) bel = solph.Bus(label='electricity') solph.Sink(label='demand', inputs={ bel: solph.Flow(fix=[209643, 207497, 200108, 191892], nominal_value=1) }) # Sources solph.Source(label='rgas', outputs={bgas: solph.Flow()}) # Transformer solph.Transformer(label='pp_gas', inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=300000)}, conversion_factors={bel: 0.58}) # Investment storage solph.components.GenericStorage( label='storage', inputs={ bel: solph.Flow( investment=solph.Investment(existing=625046 / 6, maximum=0)) }, outputs={ bel: solph.Flow( investment=solph.Investment(existing=104174.33, maximum=1)) }, loss_rate=0.00, initial_storage_level=0, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, investment=solph.Investment(ep_costs=50, existing=625046), ) # Solve model om = solph.Model(energysystem) om.solve(solver=solver) # Results results = solph.processing.results(om) electricity_bus = views.node(results, 'electricity') my_results = electricity_bus['sequences'].sum(axis=0).to_dict() storage = energysystem.groups['storage'] my_results['storage_invest'] = results[(storage, None)]['scalars']['invest']
def test_variable_chp(filename="variable_chp.csv", solver='cbc'): logging.info('Initialize the energy system') # create time index for 192 hours in May. date_time_index = pd.date_range('5/5/2012', periods=5, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) Node.registry = energysystem # Read data file with heat and electrical demand (192 hours) full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") ########################################################################## # Create oemof.solph objects ########################################################################## logging.info('Create oemof.solph objects') # create natural gas bus bgas = solph.Bus(label=('natural', 'gas')) # create commodity object for gas resource solph.Source(label=('commodity', 'gas'), outputs={bgas: solph.Flow(variable_costs=50)}) # create two electricity buses and two heat buses bel = solph.Bus(label=('electricity', 1)) bel2 = solph.Bus(label=('electricity', 2)) bth = solph.Bus(label=('heat', 1)) bth2 = solph.Bus(label=('heat', 2)) # create excess components for the elec/heat bus to allow overproduction solph.Sink(label=('excess', 'bth_2'), inputs={bth2: solph.Flow()}) solph.Sink(label=('excess', 'bth_1'), inputs={bth: solph.Flow()}) solph.Sink(label=('excess', 'bel_2'), inputs={bel2: solph.Flow()}) solph.Sink(label=('excess', 'bel_1'), inputs={bel: solph.Flow()}) # create simple sink object for electrical demand for each electrical bus solph.Sink( label=('demand', 'elec1'), inputs={bel: solph.Flow(fix=data['demand_el'], nominal_value=1)}) solph.Sink( label=('demand', 'elec2'), inputs={bel2: solph.Flow(fix=data['demand_el'], nominal_value=1)}) # create simple sink object for heat demand for each thermal bus solph.Sink( label=('demand', 'therm1'), inputs={bth: solph.Flow(fix=data['demand_th'], nominal_value=741000)}) solph.Sink( label=('demand', 'therm2'), inputs={bth2: solph.Flow(fix=data['demand_th'], nominal_value=741000)}) # create a fixed transformer to distribute to the heat_2 and elec_2 buses solph.Transformer(label=('fixed_chp', 'gas'), inputs={bgas: solph.Flow(nominal_value=10e10)}, outputs={ bel2: solph.Flow(), bth2: solph.Flow() }, conversion_factors={ bel2: 0.3, bth2: 0.5 }) # create a fixed transformer to distribute to the heat and elec buses solph.components.ExtractionTurbineCHP( label=('variable_chp', 'gas'), inputs={bgas: solph.Flow(nominal_value=10e10)}, outputs={ bel: solph.Flow(), bth: solph.Flow() }, conversion_factors={ bel: 0.3, bth: 0.5 }, conversion_factor_full_condensation={bel: 0.5}) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.Model(energysystem) logging.info('Solve the optimization problem') om.solve(solver=solver) optimisation_results = solph.processing.results(om) parameter = solph.processing.parameter_as_dict(energysystem) myresults = views.node(optimisation_results, "('natural', 'gas')") sumresults = myresults['sequences'].sum(axis=0) maxresults = myresults['sequences'].max(axis=0) variable_chp_dict_sum = { (("('natural', 'gas')", "('variable_chp', 'gas')"), 'flow'): 2823024, (("('natural', 'gas')", "('fixed_chp', 'gas')"), 'flow'): 3710208, (("('commodity', 'gas')", "('natural', 'gas')"), 'flow'): 6533232 } variable_chp_dict_max = { (("('natural', 'gas')", "('variable_chp', 'gas')"), 'flow'): 630332, (("('natural', 'gas')", "('fixed_chp', 'gas')"), 'flow'): 785934, (("('commodity', 'gas')", "('natural', 'gas')"), 'flow'): 1416266 } for key in variable_chp_dict_max.keys(): logging.debug("Test the maximum value of {0}".format(key)) eq_(int(round(maxresults[key])), int(round(variable_chp_dict_max[key]))) for key in variable_chp_dict_sum.keys(): logging.debug("Test the summed up value of {0}".format(key)) eq_(int(round(sumresults[key])), int(round(variable_chp_dict_sum[key]))) eq_( parameter[(energysystem.groups["('fixed_chp', 'gas')"], None)]['scalars']['label'], "('fixed_chp', 'gas')") eq_( parameter[(energysystem.groups["('fixed_chp', 'gas')"], None)]['scalars']["conversion_factors_('electricity', 2)"], 0.3) # objective function eq_(round(solph.processing.meta_results(om)['objective']), 326661590)
solph.Flow(my_keyword=True, fix=[0, 1, 1, 0], nominal_value=130) }) model = solph.Model(energy_system) # only one of the two flows may be active at a time solph.constraints.limit_active_flow_count_by_keyword(model, "my_keyword", lower_limit=0, upper_limit=1) model.solve() results = processing.results(model) if plt is not None: data = views.node(results, 'bel')['sequences'] ax = data.plot(kind='line', grid=True) ax.set_xlabel('Time (h)') ax.set_ylabel('P (MW)') plt.figure() ax = plt.gca() plt.plot(results[('my_keyword', 'my_keyword')]['sequences'], label="my_keyword_count") ax.set_xlabel('Time (h)') ax.set_ylabel('Count (1)') plt.grid() plt.legend() plt.show()
) ) es.add(Sink(label="load", inputs={b_el2: Flow(nominal_value=100, fix=[1, 1])})) m = Model(energysystem=es) # m.write('lopf.lp', io_options={'symbolic_solver_labels': True}) m.solve(solver="cbc", solve_kwargs={"tee": True, "keepfiles": False}) m.results() graph = create_nx_graph(es) draw_graph( graph, plot=True, layout="neato", node_size=3000, node_color={"b_0": "#cd3333", "b_1": "#7EC0EE", "b_2": "#eeac7e"}, ) results = processing.results(m) print(views.node(results, "gen_0")) print(views.node(results, "gen_1")) print(views.node(results, "line_1"))
solve_kwargs={ "tee": True, "keepfiles": False }) # write back results from optimization object to energysystem optimization_model.results() # ################################ results ################################ # subset of results that includes all flows into and from electrical bus # sequences are stored within a pandas.DataFrames and scalars e.g. # investment values within a pandas.Series object. # in this case the entry data['scalars'] does not exist since no investment # variables are used data = views.node(optimization_model.results(), "bel") data["sequences"].info() print("Optimization successful. Showing some results:") # see: https://pandas.pydata.org/pandas-docs/stable/visualization.html node_results_bel = views.node(optimization_model.results(), "bel") node_results_flows = node_results_bel["sequences"] node_results_flows.to_csv("results.csv") demand_el = node_results_flows.iloc[:, 0].sum() print("electricity demand: {:.3f}".format(demand_el)) excess_el = node_results_flows.iloc[:, 1].sum() print("{:04.1f} % excess generation: {:.3f}".format( 100 * excess_el / demand_el, excess_el)) coal_generation = node_results_flows.iloc[:, 2].sum()
def test_gen_caes(): # read sequence data full_filename = os.path.join(os.path.dirname(__file__), 'generic_caes.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 = EnergySystem(timeindex=idx) Node.registry = es # resources bgas = Bus(label='bgas') Source(label='rgas', outputs={ bgas: Flow(variable_costs=20)}) # power bel_source = Bus(label='bel_source') Source(label='source_el', outputs={ bel_source: Flow(variable_costs=data['price_el_source'])}) bel_sink = Bus(label='bel_sink') Sink(label='sink_el', inputs={ bel_sink: Flow(variable_costs=data['price_el_sink'])}) # dictionary with parameters for a specific CAES plant # based on thermal modelling and linearization techniques concept = { 'cav_e_in_b': 0, 'cav_e_in_m': 0.6457267578, 'cav_e_out_b': 0, 'cav_e_out_m': 0.3739636077, 'cav_eta_temp': 1.0, 'cav_level_max': 211.11, 'cmp_p_max_b': 86.0918959849, 'cmp_p_max_m': 0.0679999932, 'cmp_p_min': 1, 'cmp_q_out_b': -19.3996965679, 'cmp_q_out_m': 1.1066036114, 'cmp_q_tes_share': 0, 'exp_p_max_b': 46.1294016678, 'exp_p_max_m': 0.2528340303, 'exp_p_min': 1, 'exp_q_in_b': -2.2073411014, 'exp_q_in_m': 1.129249765, 'exp_q_tes_share': 0, 'tes_eta_temp': 1.0, 'tes_level_max': 0.0 } # generic compressed air energy storage (caes) plant custom.GenericCAES( label='caes', electrical_input={bel_source: Flow()}, fuel_input={bgas: Flow()}, electrical_output={bel_sink: Flow()}, params=concept, fixed_costs=0) # create an optimization problem and solve it om = Model(es) # solve model om.solve(solver='cbc') # create result object results = processing.results(om) data = views.node( results, 'caes', keep_none_type=True )['sequences'].sum(axis=0).to_dict() test_dict = { (('caes', None), 'cav_level'): 25658.82964382, (('caes', None), 'exp_p'): 5020.801997000007, (('caes', None), 'exp_q_fuel_in'): 5170.880360999999, (('caes', None), 'tes_e_out'): 0.0, (('caes', None), 'exp_st'): 226.0, (('bgas', 'caes'), 'flow'): 5170.880360999999, (('caes', None), 'cav_e_out'): 1877.5972265299995, (('caes', None), 'exp_p_max'): 17512.352336, (('caes', None), 'cmp_q_waste'): 2499.9125993000007, (('caes', None), 'cmp_p'): 2907.7271520000004, (('caes', None), 'exp_q_add_in'): 0.0, (('caes', None), 'cmp_st'): 37.0, (('caes', None), 'cmp_q_out_sum'): 2499.9125993000007, (('caes', None), 'tes_level'): 0.0, (('caes', None), 'tes_e_in'): 0.0, (('caes', None), 'exp_q_in_sum'): 5170.880360999999, (('caes', None), 'cmp_p_max'): 22320.76334300001, (('caes', 'bel_sink'), 'flow'): 5020.801997000007, (('bel_source', 'caes'), 'flow'): 2907.7271520000004, (('caes', None), 'cav_e_in'): 1877.597226} for key in test_dict.keys(): eq_(int(round(data[key])), int(round(test_dict[key])))
# add constraint for generic investment limit om = solph.constraints.additional_investment_flow_limit(om, "space", limit=24) # export lp file filename = os.path.join(helpers.extend_basic_path('lp_files'), 'GenericInvest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) # solve model om.solve(solver='cbc', solve_kwargs={'tee': True}) # create result object results = processing.results(om) bus1 = views.node(results, 'bus_a_1')["sequences"] bus2 = views.node(results, 'bus_b_1')["sequences"] # plot the time series (sequences) of a specific component/bus if plt is not None: bus1.plot(kind='line', drawstyle='steps-mid') plt.legend() plt.show() bus2.plot(kind='line', drawstyle='steps-mid') plt.legend() plt.show() space_used = om.invest_limit_space() print('Space value: ', space_used) print('Investment trafo_a: ', views.node(results, 'trafo_a')["scalars"][0]) print('Investment trafo_b: ', views.node(results, 'trafo_b')["scalars"][0])
def test_dispatch_fix_example(solver='cbc', periods=10): """Invest in a flow with a `fix` sequence containing values > 1.""" Node.registry = None filename = os.path.join(os.path.dirname(__file__), 'input_data.csv') data = pd.read_csv(filename, sep=",") # ######################### create energysystem components ################ # electricity and heat bel = Bus(label='b_el') # an excess and a shortage variable can help to avoid infeasible problems excess_el = Sink(label='excess_el', inputs={bel: Flow()}) # shortage_el = Source(label='shortage_el', # outputs={bel: Flow(variable_costs=200)}) # sources ep_pv = economics.annuity(capex=1500, n=20, wacc=0.05) pv = Source(label='pv', outputs={ bel: Flow(fix=data['pv'], investment=Investment(ep_costs=ep_pv)) }) # demands (electricity/heat) demand_el = Sink( label='demand_elec', inputs={bel: Flow(nominal_value=85, fix=data['demand_el'])}) datetimeindex = pd.date_range('1/1/2012', periods=periods, freq='H') energysystem = EnergySystem(timeindex=datetimeindex) energysystem.add(bel, excess_el, pv, demand_el) # ################################ optimization ########################### # create optimization model based on energy_system optimization_model = Model(energysystem=energysystem) # solve problem optimization_model.solve(solver=solver) # ################################ results ################################ # generic result object results = processing.results(om=optimization_model) # subset of results that includes all flows into and from electrical bus # sequences are stored within a pandas.DataFrames and scalars e.g. # investment values within a pandas.Series object. # in this case the entry data['scalars'] does not exist since no investment # variables are used data = views.node(results, 'b_el') # generate results to be evaluated in tests comp_results = data['sequences'].sum(axis=0).to_dict() comp_results['pv_capacity'] = results[(pv, bel)]['scalars'].invest assert comp_results[(('pv', 'b_el'), 'flow')] > 0
def test_connect_invest(): date_time_index = pd.date_range('1/1/2012', periods=24 * 7, freq='H') energysystem = EnergySystem(timeindex=date_time_index) network.Node.registry = energysystem # Read data file full_filename = os.path.join(os.path.dirname(__file__), 'connect_invest.csv') data = pd.read_csv(full_filename, sep=",") logging.info('Create oemof objects') # create electricity bus bel1 = Bus(label="electricity1") bel2 = Bus(label="electricity2") # create excess component for the electricity bus to allow overproduction Sink(label='excess_bel', inputs={bel2: Flow()}) Source(label='shortage', outputs={bel2: Flow(variable_costs=50000)}) # create fixed source object representing wind power plants Source(label='wind', outputs={bel1: Flow(fix=data['wind'], nominal_value=1000000)}) # create simple sink object representing the electrical demand Sink(label='demand', inputs={bel1: Flow(fix=data['demand_el'], nominal_value=1)}) storage = components.GenericStorage( label='storage', inputs={bel1: Flow(variable_costs=10e10)}, outputs={bel1: Flow(variable_costs=10e10)}, loss_rate=0.00, initial_storage_level=0, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, investment=Investment(ep_costs=0.2), ) line12 = Transformer( label="line12", inputs={bel1: Flow()}, outputs={bel2: Flow(investment=Investment(ep_costs=20))}) line21 = Transformer( label="line21", inputs={bel2: Flow()}, outputs={bel1: Flow(investment=Investment(ep_costs=20))}) om = Model(energysystem) constraints.equate_variables(om, om.InvestmentFlow.invest[line12, bel2], om.InvestmentFlow.invest[line21, bel1], 2) constraints.equate_variables( om, om.InvestmentFlow.invest[line12, bel2], om.GenericInvestmentStorageBlock.invest[storage]) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') om.solve(solver='cbc') # check if the new result object is working for custom components results = processing.results(om) my_results = dict() my_results['line12'] = float(views.node(results, 'line12')['scalars']) my_results['line21'] = float(views.node(results, 'line21')['scalars']) stor_res = views.node(results, 'storage')['scalars'] my_results['storage_in'] = stor_res[(('electricity1', 'storage'), 'invest')] my_results['storage'] = stor_res[(('storage', 'None'), 'invest')] my_results['storage_out'] = stor_res[(('storage', 'electricity1'), 'invest')] connect_invest_dict = { 'line12': 814705, 'line21': 1629410, 'storage': 814705, 'storage_in': 135784, 'storage_out': 135784 } for key in connect_invest_dict.keys(): eq_(int(round(my_results[key])), int(round(connect_invest_dict[key])))
def postprocessing(results, param, data): """ Perform postprocessing of optimization results. Parameters ---------- results : dict of pandas.Series and pandas.DataFrame Full results from solph.processing.results() call. param : dict JSON parameter file of user defined constants. data : pandas.DataFrame csv file of user defined time dependent parameters. """ data_cost_units = pd.DataFrame() 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'] data_wnw_node = views.node(results, 'TES Knoten')['sequences'] data_sol_node = views.node(results, 'Sol Knoten')['sequences'] if param['Sol']['active']: data_solar_source = views.node(results, 'Solarthermie')['sequences'] data_cost_units.loc['invest', 'Sol'] = (invest_sol(param['Sol']['A'], col_type='flat')) data_cost_units.loc['op_cost', 'Sol'] = ( data_solar_source[(('Solarthermie', 'Sol Knoten'), 'flow')].sum() * 0.01 * data_cost_units.loc['invest', 'Sol'] / param['Sol']['A'] * data['solar_data_' + param['Sol']['usage']].sum()) if param['EHK']['active']: data_cost_units.loc['invest', 'EHK'] = (param['EHK']['inv_spez'] * param['EHK']['Q_N'] * param['EHK']['amount']) data_cost_units.loc['op_cost', 'EHK'] = 0 for i in range(1, param['EHK']['amount'] + 1): label_id = 'Elektroheizkessel_' + str(i) data_cost_units.loc['op_cost', 'EHK'] += ( data_wnw[((label_id, 'Wärmenetzwerk'), 'flow')].sum() * param['EHK']['op_cost_var'] + (param['EHK']['op_cost_fix'] * param['EHK']['Q_N'])) if param['SLK']['active']: data_cost_units.loc['invest', 'SLK'] = (param['SLK']['inv_spez'] * param['SLK']['Q_N'] * param['SLK']['amount']) data_cost_units.loc['op_cost', 'SLK'] = 0 for i in range(1, param['SLK']['amount'] + 1): label_id = 'Spitzenlastkessel_' + str(i) data_cost_units.loc['op_cost', 'SLK'] += ( data_wnw[((label_id, 'Wärmenetzwerk'), 'flow')].sum() * (param['SLK']['op_cost_var'] + param['param']['energy_tax']) + (param['SLK']['op_cost_fix'] * param['SLK']['Q_N'])) if param['BHKW']['active']: if param['BHKW']['type'] == 'constant': ICE_P_max_woDH = param['BHKW']['P_max_woDH'] elif param['BHKW']['type'] == 'time series': ICE_P_max_woDH = data['ICE_P_max_woDH'].mean() data_cost_units.loc['invest', 'BHKW'] = (ICE_P_max_woDH * param['BHKW']['inv_spez'] * param['BHKW']['amount']) data_cost_units.loc['op_cost', 'BHKW'] = 0 for i in range(1, param['BHKW']['amount'] + 1): label_id = 'BHKW_' + str(i) data_cost_units.loc['op_cost', 'BHKW'] += ( data_enw[((label_id, 'Elektrizitätsnetzwerk'), 'flow')].sum() * param['BHKW']['op_cost_var'] + (param['BHKW']['op_cost_fix'] * ICE_P_max_woDH)) if param['GuD']['active']: if param['GuD']['type'] == 'constant': CCET_P_max_woDH = param['GuD']['P_max_woDH'] elif param['GuD']['type'] == 'time series': CCET_P_max_woDH = data['CCET_P_max_woDH'].mean() data_cost_units.loc['invest', 'GuD'] = (CCET_P_max_woDH * param['GuD']['inv_spez'] * param['GuD']['amount']) data_cost_units.loc['op_cost', 'GuD'] = 0 for i in range(1, param['GuD']['amount'] + 1): label_id = 'GuD_' + str(i) data_cost_units.loc['op_cost', 'GuD'] += ( data_enw[((label_id, 'Elektrizitätsnetzwerk'), 'flow')].sum() * param['GuD']['op_cost_var'] + (param['GuD']['op_cost_fix'] * CCET_P_max_woDH)) if param['HP']['active']: if param['HP']['type'] == 'constant': HP_Q_N = (param['HP']['c_1'] * param['HP']['P_max'] + param['HP']['c_0']) elif param['HP']['type'] == 'time series': HP_Q_N = (data['c_1_hp'].mean() * data['P_max_hp'].mean() + data['c_0_hp'].mean()) data_cost_units.loc['invest', 'HP'] = (param['HP']['inv_spez'] * data['P_max_hp'].max() * HP_Q_N * param['HP']['amount']) data_cost_units.loc['op_cost', 'HP'] = 0 for i in range(1, param['HP']['amount'] + 1): label_id = 'HP_' + str(i) data_cost_units.loc['op_cost', 'HP'] += ( data_wnw[((label_id, 'Wärmenetzwerk'), 'flow')].sum() * param['HP']['op_cost_var'] + param['HP']['op_cost_fix'] * HP_Q_N) if param['LT-HP']['active']: LT_HP_Q_N = data_wnw[((label_id, 'Wärmenetzwerk'), 'flow')].mean() data_cost_units.loc['invest', 'LT-HP'] = 0 data_cost_units.loc['op_cost', 'LT-HP'] = 0 for i in range(1, param['LT-HP']['amount'] + 1): label_id = 'LT-HP_' + str(i) data_cost_units.loc['invest', 'LT-HP'] += (param['HP']['inv_spez'] * LT_HP_Q_N) data_cost_units.loc['op_cost', 'LT-HP'] += ( data_wnw[((label_id, 'Wärmenetzwerk'), 'flow')].sum() * param['HP']['op_cost_var'] + param['HP']['op_cost_fix'] * LT_HP_Q_N) data_tes = pd.DataFrame() if param['TES']['active']: data_cost_units.loc['invest', 'TES'] = (invest_stes(param['TES']['Q']) * param['TES']['amount']) data_cost_units.loc['op_cost', 'TES'] = 0 for i in range(1, param['TES']['amount'] + 1): label_id = 'TES_' + str(i) data_tes = pd.concat( [data_tes, views.node(results, label_id)['sequences']], axis=1) data_cost_units.loc['op_cost', 'TES'] += ( data_tes[(('TES Knoten', label_id), 'flow')].sum() * param['TES']['op_cost_var'] + (param['TES']['op_cost_fix'] * param['TES']['Q'])) if param['ST-TES']['active']: data_cost_units.loc['invest', 'ST-TES'] = (invest_stes(param['ST-TES']['Q']) * param['ST-TES']['amount']) data_cost_units.loc['op_cost', 'ST-TES'] = 0 for i in range(1, param['ST-TES']['amount'] + 1): label_id = 'ST-TES_' + str(i) data_tes = pd.concat( [data_tes, views.node(results, label_id)['sequences']], axis=1) data_cost_units.loc['op_cost', 'ST-TES'] += ( data_tes[(('Wärmenetzwerk', label_id), 'flow')].sum() * param['ST-TES']['op_cost_var'] + (param['ST-TES']['op_cost_fix'] * param['ST-TES']['Q'])) cost_Anlagen = data_cost_units.loc['op_cost'].sum() invest_ges = data_cost_units.loc['invest'].sum() cost_gas = (data_gnw[(('Gasquelle', 'Gasnetzwerk'), 'flow')].sum() * (param['param']['gas_price'] + (param['param']['co2_price'] * param['param']['ef_gas']))) specific_costs_el_grid = (param['param']['elec_consumer_charges_grid'] + data['el_spot_price'] + (param['param']['co2_price'] * data['ef_om'])) cost_el_grid = (np.array(data_enw[( ('Stromquelle', 'Elektrizitätsnetzwerk'), 'flow')]) * specific_costs_el_grid) cost_el_grid = cost_el_grid.sum() cost_el_internal = ( (data_enw.loc[:, ['BHKW' in col for col in data_enw.columns]].to_numpy().sum() + data_enw.loc[:, ['GuD' in col for col in data_enw.columns]].to_numpy().sum() - data_enw[(('Elektrizitätsnetzwerk', 'Spotmarkt'), 'flow')].sum()) * param['param']['elec_consumer_charges_self']) cost_el = cost_el_grid + cost_el_internal revenues_spotmarkt_timeseries = ( np.array(data_enw[(('Elektrizitätsnetzwerk', 'Spotmarkt'), 'flow')]) * (data['el_spot_price'] + param['param']['vNNE'])) revenues_spotmarkt = revenues_spotmarkt_timeseries.sum() revenues_chpbonus = 0 if param['BHKW']['active']: revenues_chpbonus += ( data_enw.loc[:, ['BHKW' in col for col in data_enw.columns]].to_numpy().sum() * (param['BHKW']['chp_bonus'] + param['BHKW']['TEHG_bonus'])) if param['GuD']['active']: revenues_chpbonus += ( data_enw.loc[:, ['GuD' in col for col in data_enw.columns]].to_numpy().sum() * (param['GuD']['chp_bonus'] + param['GuD']['TEHG_bonus'])) if param['BPT']['active']: revenues_chpbonus += ( data_enw.loc[:, ['BPT' in col for col in data_enw.columns]].to_numpy().sum() * (param['BPT']['chp_bonus'] + param['BPT']['TEHG_bonus'])) revenues_heatdemand = (data_wnw[( ('Wärmenetzwerk', 'Wärmebedarf'), 'flow')].sum() * param['param']['heat_price']) revenues_total = (revenues_spotmarkt + revenues_heatdemand + revenues_chpbonus) cost_total = cost_Anlagen + cost_gas + cost_el Gesamtbetrag = revenues_total - cost_total result_dfs = [ data_wnw, data_lt_wnw, data_wnw_node, data_sol_node, data_tes, data_enw, data_gnw ] labeldict = generate_labeldict(param) for df in result_dfs: result_labelling(labeldict, df) data_dhs = pd.concat(result_dfs, axis=1) data_invest = pd.DataFrame( data={ 'invest_ges': [invest_ges], 'Q_tes': [param['TES']['Q']], 'total_heat_demand': [data['heat_demand'].sum() * param['param']['rel_demand']], 'Gesamtbetrag': [Gesamtbetrag], 'revenues_spotmarkt': [revenues_spotmarkt], 'revenues_heatdemand': [revenues_heatdemand], 'revenues_chpbonus': [revenues_chpbonus], 'cost_Anlagen': [cost_Anlagen], 'cost_gas': [cost_gas], 'cost_el': [cost_el], 'cost_el_grid': [cost_el_grid], 'cost_el_internal': [cost_el_internal], 'cost_total': [cost_total], 'revenues_total': [revenues_total] }) data_emission = pd.concat( [data_gnw['H_source'], data_enw[['P_spot_market', 'P_source']]], axis=1) return data_dhs, data_invest, data_emission, data_cost_units
def test_dispatch_one_time_step(solver='cbc'): """Create an energy system and optimize the dispatch at least costs.""" # ######################### create energysystem components ################ Node.registry = None # resource buses bgas = Bus(label='gas', balanced=False) # electricity and heat bel = Bus(label='b_el') bth = Bus(label='b_th') # an excess and a shortage variable can help to avoid infeasible problems excess_el = Sink(label='excess_el', inputs={bel: Flow()}) # sources wind = Source(label='wind', outputs={bel: Flow(fix=0.5, nominal_value=66.3)}) # demands (electricity/heat) demand_el = Sink(label='demand_elec', inputs={bel: Flow(nominal_value=85, fix=0.3)}) demand_th = Sink(label='demand_therm', inputs={bth: Flow(nominal_value=40, fix=0.2)}) # combined heat and power plant (chp) pp_chp = Transformer(label='pp_chp', inputs={bgas: Flow()}, outputs={ bel: Flow(nominal_value=30, variable_costs=42), bth: Flow(nominal_value=40) }, conversion_factors={ bel: 0.3, bth: 0.4 }) # heatpump with a coefficient of performance (COP) of 3 b_heat_source = Bus(label='b_heat_source') heat_source = Source(label='heat_source', outputs={b_heat_source: Flow()}) cop = 3 heat_pump = Transformer(label='heat_pump', inputs={ bel: Flow(), b_heat_source: Flow() }, outputs={bth: Flow(nominal_value=10)}, conversion_factors={ bel: 1 / 3, b_heat_source: (cop - 1) / cop }) energysystem = EnergySystem(timeindex=[1]) energysystem.add(bgas, bel, bth, excess_el, wind, demand_el, demand_th, pp_chp, b_heat_source, heat_source, heat_pump) # ################################ optimization ########################### # create optimization model based on energy_system optimization_model = Model(energysystem=energysystem, timeincrement=1) # solve problem optimization_model.solve(solver=solver) # write back results from optimization object to energysystem optimization_model.results() # ################################ results ################################ data = views.node(processing.results(om=optimization_model), 'b_el') # generate results to be evaluated in tests results = data['sequences'].sum(axis=0).to_dict() test_results = { (('wind', 'b_el'), 'flow'): 33, (('b_el', 'demand_elec'), 'flow'): 26, (('b_el', 'excess_el'), 'flow'): 5, (('b_el', 'heat_pump'), 'flow'): 3, } for key in test_results.keys(): eq_(int(round(results[key])), int(round(test_results[key])))
m = Model(energysystem=es) # m.write('transshipment.lp', io_options={'symbolic_solver_labels': True}) m.solve(solver='cbc', solve_kwargs={'tee': True, 'keepfiles': False}) m.results() graph = create_nx_graph(es, m) draw_graph(graph, plot=True, layout='neato', node_size=3000, node_color={ 'b_0': '#cd3333', 'b_1': '#7EC0EE', 'b_2': '#eeac7e' }) results = processing.results(m) print(views.node(results, 'gen_0')) print(views.node(results, 'gen_1')) views.node(results, 'line_0')['sequences'].plot(kind='bar') # look at constraints of Links in the pyomo model LinkBlock m.LinkBlock.pprint()
# %% 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.loc[('Sol', 'active'), 'value'] == 1: data_solar_source = views.node(results, 'Solarthermie')['sequences']
def electric_postprocessing(config_path, var_number): global df_all_var with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.CLoader) # Define the used directories abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) results_path = abs_path + '/results' csv_path = results_path + '/optimisation_results/' plot_path = results_path + '/plots/' energysystem = solph.EnergySystem() energysystem.restore(dpath=(results_path + '/dumps'), filename='electric_model_{0}_{1}.oemof'.format( cfg['exp_number'], var_number)) sp = cfg['start_of_plot'] ep = cfg['end_of_plot'] # Look up investment costs. Therefor parameters must read again. if type(cfg['parameters_variation']) == list: file_path_param_01 = abs_path + '/data/data_public/' + cfg[ 'parameters_system'] file_path_param_02 = abs_path + '/data/data_public/' + cfg[ 'parameters_variation'][var_number] elif type(cfg['parameters_system']) == list: file_path_param_01 = abs_path + '/data/data_public/' + cfg[ 'parameters_system'][var_number] file_path_param_02 = abs_path + '/data/data_public/' + cfg[ 'parameters_variation'] else: file_path_param_01 = abs_path + '/data/data_public/' + cfg[ 'parameters_system'] file_path_param_02 = abs_path + '/data/data_public/' + cfg[ 'parameters_variation'] param_df_01 = pd.read_csv(file_path_param_01, index_col=1) param_df_02 = pd.read_csv(file_path_param_02, index_col=1) param_df = pd.concat([param_df_01, param_df_02], sort=True) param_value = param_df['value'] logging.info('results received') ######################### # Work with the results # ######################### cool_bus = views.node(energysystem.results['main'], 'cool') waste_bus = views.node(energysystem.results['main'], 'waste') el_bus = views.node(energysystem.results['main'], 'electricity') ambient_res = views.node(energysystem.results['main'], 'ambient') none_res = views.node(energysystem.results['main'], 'None') # Sequences: cool_seq = cool_bus['sequences'] waste_seq = waste_bus['sequences'] el_seq = el_bus['sequences'] ambient_seq = ambient_res['sequences'] # Scalars cool_scal = cool_bus['scalars'] waste_scal = waste_bus['scalars'] el_scal = el_bus['scalars'] none_scal = none_res['scalars'] none_scal_given = views.node(energysystem.results['param'], 'None')['scalars'] el_scal[(('pv', 'electricity'), 'invest')] = (el_scal[(('pv', 'electricity'), 'invest')] * param_value['size_pv']) # Conversion of the pv-investment-size, because Invest-object is normalized # at 0.970873786 kWpeak # solar fraction # electric: # control_el (No Power must go from grid to excess) df_control_el = pd.DataFrame() df_control_el['grid_el'] = el_seq[(('grid_el', 'electricity'), 'flow')] df_control_el['excess'] = el_seq[(('electricity', 'excess_el'), 'flow')] df_control_el['Product'] = (df_control_el['grid_el'] * df_control_el['excess']) el_from_grid = el_seq[(('grid_el', 'electricity'), 'flow')].sum() el_from_pv = el_seq[(('pv', 'electricity'), 'flow')].sum() el_to_excess = el_seq[(('electricity', 'excess_el'), 'flow')].sum() el_pv_used = el_from_pv - el_to_excess sol_fraction_el = el_pv_used / (el_pv_used + el_from_grid) # Power usage: el_used = el_seq[(('grid_el', 'electricity'), 'flow')].sum() # Power to the output: electricity_output = el_seq[(('electricity', 'excess_el'), 'flow')].sum() electricity_output_pv = el_seq[(('pv', 'electricity'), 'flow')].sum() # ## costs ## # costs_total = energysystem.results['meta']['objective'] # Storage costs must be subtract for reference scenario or added # for the other scenarios. # reference scenario: if param_value['nominal_capacitiy_stor_el'] == 0: costs_total_wo_stor = ( costs_total - (none_scal[( ('storage_electricity', 'None'), 'invest')] * none_scal_given[( ('storage_electricity', 'None'), 'investment_ep_costs')]) - (none_scal[( ('storage_cool', 'None'), 'invest')] * none_scal_given[( ('storage_cool', 'None'), 'investment_ep_costs')])) # other scenarios: else: # calculation of ep_costs ep_costs_el_stor = ep_costs_func( param_value['invest_costs_stor_el_capacity'], param_value['lifetime_stor_el'], param_value['opex_stor_el'], param_value['wacc']) ep_costs_cool_stor = ep_costs_func( param_value['invest_costs_stor_cool_capacity'], param_value['lifetime_stor_cool'], param_value['opex_stor_cool'], param_value['wacc']) # calculation of the scenario costs inclusive storage costs costs_total_w_stor = ( costs_total + (none_scal_given[(('storage_cool', 'None'), 'nominal_capacity')] * ep_costs_cool_stor) + (none_scal_given[( ('storage_electricity', 'None'), 'nominal_capacity')] * ep_costs_el_stor)) ######################## # Write results in csv # ######################## # ## scalars ## # # base scalars: scalars_all = cool_scal\ .append(waste_scal)\ .append(el_scal)\ .append(none_scal) for i in range(0, none_scal_given.count()): if 'nominal_capacity' in none_scal_given.index[i]: scalars_all = pd.concat([ scalars_all, pd.Series([none_scal_given[i]], index=[none_scal_given.index[i]]) ]) # solar fractions scalars_all = pd.concat([ scalars_all, pd.Series([sol_fraction_el], index=["('solar fraction', 'electric'), ' ')"]) ]) if df_control_el['Product'].sum() != 0: scalars_all = pd.concat([ scalars_all, pd.Series([df_control_el['Product'].sum()], index=["Has to be 0!!!"]) ]) # various results scalars_all = pd.concat([ scalars_all, pd.Series([el_used], index=["('grid_el', 'electricity'), 'summe')"]) ]) scalars_all = pd.concat([ scalars_all, pd.Series([electricity_output], index=["('electricity', 'output'), 'summe')"]) ]) scalars_all = pd.concat([ scalars_all, pd.Series([electricity_output_pv], index=["('pv', 'electricity'), 'summe')"]) ]) # costs with or without storage (depends on reference scenario or not) if param_value['nominal_capacitiy_stor_el'] != 0: scalars_all = pd.concat([ scalars_all, pd.Series([costs_total_w_stor], index=["('costs', 'w_stor'), 'per year')"]) ]) scalars_all = pd.concat([ scalars_all, pd.Series([costs_total], index=["('costs', 'wo_stor'), 'per year')"]) ]) if param_value['nominal_capacitiy_stor_el'] == 0: scalars_all = pd.concat([ scalars_all, pd.Series([costs_total_wo_stor], index=["('costs', 'wo stor'), 'per year')"]) ]) # experiment number and variation scalars_all = pd.concat([ scalars_all, pd.Series(['{0}_{1}'.format(cfg['exp_number'], var_number)], index=["('Exp', 'Var'), 'number')"]) ]) # write scalars into csv for this experiment and variation scalars_all.to_csv(csv_path + 'electric_model_{0}_{1}_scalars.csv'.format( cfg['exp_number'], var_number), header=False) # write scalars for all variations of the experiment into csv df_all_var = pd.concat([df_all_var, scalars_all], axis=1, sort=True) if var_number == (cfg['number_of_variations'] - 1): df_all_var.to_csv(csv_path + 'electric_model_{0}_scalars_all_variations.csv'. format(cfg['exp_number'])) logging.info('Writing the results for all variations into csv') # ## sequences ## # sequences_df = pd.merge(ambient_seq, waste_seq, left_index=True, right_index=True) sequences_df = pd.merge(sequences_df, el_seq, left_index=True, right_index=True) sequences_df = pd.merge(sequences_df, cool_seq, left_index=True, right_index=True) sequences_df.to_csv(csv_path + 'electric_model_{0}_{1}_sequences.csv'.format( cfg['exp_number'], var_number), header=False) ######################## # Plotting the results # # to adapt for the use case ######################## cool_seq_resample = cool_seq.iloc[sp:ep] waste_seq_resample = waste_seq.iloc[sp:ep] el_seq_resample = el_seq.iloc[sp:ep] ambient_seq_resample = ambient_seq.iloc[sp:ep] def shape_legend(node, reverse=False, **kwargs): # just copied handels = kwargs['handles'] labels = kwargs['labels'] axes = kwargs['ax'] parameter = {} new_labels = [] for label in labels: label = label.replace('(', '') label = label.replace('), flow)', '') label = label.replace(node, '') label = label.replace(',', '') label = label.replace(' ', '') new_labels.append(label) labels = new_labels parameter['bbox_to_anchor'] = kwargs.get('bbox_to_anchor', (1, 1)) parameter['loc'] = kwargs.get('loc', 'upper left') parameter['ncol'] = kwargs.get('ncol', 1) plotshare = kwargs.get('plotshare', 0.9) if reverse: handels = handels.reverse() labels = labels.reverse() box = axes.get_position() axes.set_position([box.x0, box.y0, box.width * plotshare, box.height]) parameter['handles'] = handels parameter['labels'] = labels axes.legend(**parameter) return axes cdict = { (('storage_cool', 'cool'), 'flow'): '#555555', (('cool', 'storage_cool'), 'flow'): '#9acd32', (('cool', 'demand'), 'flow'): '#cd0000', (('grid_el', 'electricity'), 'flow'): '#999999', (('pv', 'electricity'), 'flow'): '#ffde32', (('storage_electricity', 'electricity'), 'flow'): '#9acd32', (('electricity', 'storage_electricity'), 'flow'): '#9acd32', (('electricity', 'compression_chiller'), 'flow'): '#4682b4', (('electricity', 'cooling_tower'), 'flow'): '#ff0000', (('storage_cool', 'None'), 'capacity'): '#555555', (('storage_cool', 'cool'), 'flow'): '#9acd32', (('compression_chiller', 'waste'), 'flow'): '#4682b4', (('electricity', 'excess_el'), 'flow'): '#999999', (('waste', 'cool_tower'), 'flow'): '#42c77a' } # define order of inputs and outputs inorderel = [(('pv', 'electricity'), 'flow'), (('storage_electricity', 'electricity'), 'flow'), (('grid_el', 'electricity'), 'flow')] outorderel = [(('electricity', 'compression_chiller'), 'flow'), (('electricity', 'cooling_tower'), 'flow'), (('electricity', 'storage_electricity'), 'flow'), (('electricity', 'excess_el'), 'flow')] fig = plt.figure(figsize=(15, 15)) # plot electrical energy my_plot_el = oev.plot.io_plot('electricity', el_seq_resample, cdict=cdict, inorder=inorderel, outorder=outorderel, ax=fig.add_subplot(2, 2, 1), smooth=False) ax_el = shape_legend('electricity', **my_plot_el) ax_el.set_ylabel('Power in kW') ax_el.set_xlabel('time') ax_el.set_title("results of the electric model - electricity flows") plt.savefig(plot_path + 'electric_model_results_plot_{0}_{1}.png'.format( cfg['exp_number'], var_number)) csv_plot = pd.merge(el_seq_resample, cool_seq_resample, left_index=True, right_index=True) csv_plot = pd.merge(csv_plot, el_seq_resample, left_index=True, right_index=True) csv_plot.to_csv(plot_path + 'electric_model_results_plot_data_{0}_{1}.csv'.format( cfg['exp_number'], var_number)) return df_all_var
def test_multiindex_sequences(self): results = processing.results(self.om) bel1 = views.node(results, 'b_el1', multiindex=True) eq_(int(bel1['sequences'][('diesel', 'b_el1', 'flow')].sum()), 2875)
def test_gen_chp(): # read sequence data full_filename = os.path.join(os.path.dirname(__file__), 'ccet.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(fix=data['demand_th'], nominal_value=200)}) # power bel = solph.Bus(label='bel') solph.Sink(label='demand_el', inputs={bel: solph.Flow(variable_costs=data['price_el'])}) # generic chp # (for back pressure characteristics Q_CW_min=0 and back_pressure=True) solph.components.GenericCHP( label='combined_cycle_extraction_turbine', fuel_input={ bgas: solph.Flow(H_L_FG_share_max=data['H_L_FG_share_max']) }, electrical_output={ bel: solph.Flow(P_max_woDH=data['P_max_woDH'], P_min_woDH=data['P_min_woDH'], Eta_el_max_woDH=data['Eta_el_max_woDH'], Eta_el_min_woDH=data['Eta_el_min_woDH']) }, heat_output={bth: solph.Flow(Q_CW_min=data['Q_CW_min'])}, Beta=data['Beta'], back_pressure=False) # 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 = { (('bth', 'demand_th'), 'flow'): 20000.0, (('combined_cycle_extraction_turbine', 'bth'), 'flow'): 14070.15215799, (('source_th', 'bth'), 'flow'): 5929.8478649200015 } for key in test_dict.keys(): eq_(int(round(data[key])), int(round(test_dict[key])))
def test_duals(self): results = processing.results(self.om) bel = views.node(results, 'b_el1', multiindex=True) eq_(int(bel['sequences']['b_el1', 'None', 'duals'].sum()), 48)
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=";")
def test_input_by_type_view(self): results = processing.results(self.om) sink_input = views.node_input_by_type(results, node_type=Sink) compare = views.node(results, 'demand_el', multiindex=True) eq_(int(sink_input.sum()), int(compare['sequences'][('b_el2', 'demand_el', 'flow')].sum()))
def test_dispatch_example(solver='cbc', periods=24*5): """Create an energy system and optimize the dispatch at least costs.""" Node.registry = None filename = os.path.join(os.path.dirname(__file__), 'input_data.csv') data = pd.read_csv(filename, sep=",") # ######################### create energysystem components ################ # resource buses bcoal = Bus(label='coal', balanced=False) bgas = Bus(label='gas', balanced=False) boil = Bus(label='oil', balanced=False) blig = Bus(label='lignite', balanced=False) # electricity and heat bel = Bus(label='b_el') bth = Bus(label='b_th') # an excess and a shortage variable can help to avoid infeasible problems excess_el = Sink(label='excess_el', inputs={bel: Flow()}) # shortage_el = Source(label='shortage_el', # outputs={bel: Flow(variable_costs=200)}) # sources ep_wind = economics.annuity(capex=1000, n=20, wacc=0.05) wind = Source(label='wind', outputs={bel: Flow( fix=data['wind'], investment=Investment(ep_costs=ep_wind, existing=100))}) ep_pv = economics.annuity(capex=1500, n=20, wacc=0.05) pv = Source(label='pv', outputs={bel: Flow( fix=data['pv'], investment=Investment(ep_costs=ep_pv, existing=80))}) # demands (electricity/heat) demand_el = Sink(label='demand_elec', inputs={bel: Flow(nominal_value=85, fix=data['demand_el'])}) demand_th = Sink(label='demand_therm', inputs={bth: Flow(nominal_value=40, fix=data['demand_th'])}) # power plants pp_coal = Transformer(label='pp_coal', inputs={bcoal: Flow()}, outputs={bel: Flow(nominal_value=20.2, variable_costs=25)}, conversion_factors={bel: 0.39}) pp_lig = Transformer(label='pp_lig', inputs={blig: Flow()}, outputs={bel: Flow(nominal_value=11.8, variable_costs=19)}, conversion_factors={bel: 0.41}) pp_gas = Transformer(label='pp_gas', inputs={bgas: Flow()}, outputs={bel: Flow(nominal_value=41, variable_costs=40)}, conversion_factors={bel: 0.50}) pp_oil = Transformer(label='pp_oil', inputs={boil: Flow()}, outputs={bel: Flow(nominal_value=5, variable_costs=50)}, conversion_factors={bel: 0.28}) # combined heat and power plant (chp) pp_chp = Transformer(label='pp_chp', inputs={bgas: Flow()}, outputs={bel: Flow(nominal_value=30, variable_costs=42), bth: Flow(nominal_value=40)}, conversion_factors={bel: 0.3, bth: 0.4}) # heatpump with a coefficient of performance (COP) of 3 b_heat_source = Bus(label='b_heat_source') heat_source = Source(label='heat_source', outputs={b_heat_source: Flow()}) cop = 3 heat_pump = Transformer(label='el_heat_pump', inputs={bel: Flow(), b_heat_source: Flow()}, outputs={bth: Flow(nominal_value=10)}, conversion_factors={ bel: 1/3, b_heat_source: (cop-1)/cop}) datetimeindex = pd.date_range('1/1/2012', periods=periods, freq='H') energysystem = EnergySystem(timeindex=datetimeindex) energysystem.add(bcoal, bgas, boil, bel, bth, blig, excess_el, wind, pv, demand_el, demand_th, pp_coal, pp_lig, pp_oil, pp_gas, pp_chp, b_heat_source, heat_source, heat_pump) # ################################ optimization ########################### # create optimization model based on energy_system optimization_model = Model(energysystem=energysystem) # solve problem optimization_model.solve(solver=solver) # write back results from optimization object to energysystem optimization_model.results() # ################################ results ################################ # generic result object results = processing.results(om=optimization_model) # subset of results that includes all flows into and from electrical bus # sequences are stored within a pandas.DataFrames and scalars e.g. # investment values within a pandas.Series object. # in this case the entry data['scalars'] does not exist since no investment # variables are used data = views.node(results, 'b_el') # generate results to be evaluated in tests comp_results = data['sequences'].sum(axis=0).to_dict() comp_results['pv_capacity'] = results[(pv, bel)]['scalars'].invest comp_results['wind_capacity'] = results[(wind, bel)]['scalars'].invest test_results = { (('wind', 'b_el'), 'flow'): 9239, (('pv', 'b_el'), 'flow'): 1147, (('b_el', 'demand_elec'), 'flow'): 7440, (('b_el', 'excess_el'), 'flow'): 6261, (('pp_chp', 'b_el'), 'flow'): 477, (('pp_lig', 'b_el'), 'flow'): 850, (('pp_gas', 'b_el'), 'flow'): 934, (('pp_coal', 'b_el'), 'flow'): 1256, (('pp_oil', 'b_el'), 'flow'): 0, (('b_el', 'el_heat_pump'), 'flow'): 202, 'pv_capacity': 44, 'wind_capacity': 246, } for key in test_results.keys(): eq_(int(round(comp_results[key])), int(round(test_results[key])))
def test_tuples_as_labels_example(filename="storage_investment.csv", solver='cbc'): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=40, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) Node.registry = energysystem full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") # Buses bgas = solph.Bus(label=Label('bus', 'natural_gas', None)) bel = solph.Bus(label=Label('bus', 'electricity', '')) # Sinks solph.Sink(label=Label('sink', 'electricity', 'excess'), inputs={bel: solph.Flow()}) solph.Sink( label=Label('sink', 'electricity', 'demand'), inputs={bel: solph.Flow(fix=data['demand_el'], nominal_value=1)}) # Sources solph.Source(label=Label('source', 'natural_gas', 'commodity'), outputs={ bgas: solph.Flow(nominal_value=194397000 * 400 / 8760, summed_max=1) }) solph.Source( label=Label('renewable', 'electricity', 'wind'), outputs={bel: solph.Flow(fix=data['wind'], nominal_value=1000000)}) solph.Source( label=Label('renewable', 'electricity', 'pv'), outputs={bel: solph.Flow( fix=data['pv'], nominal_value=582000, )}) # Transformer solph.Transformer( label=Label('pp', 'electricity', 'natural_gas'), inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) # Investment storage solph.components.GenericStorage( label=Label('storage', 'electricity', 'battery'), nominal_storage_capacity=204685, inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, loss_rate=0.00, initial_storage_level=0, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, ) # Solve model om = solph.Model(energysystem) om.solve(solver=solver) energysystem.results['main'] = processing.results(om) energysystem.results['meta'] = processing.meta_results(om) # Check dump and restore energysystem.dump() es = solph.EnergySystem() es.restore() # Results results = es.results['main'] meta = es.results['meta'] electricity_bus = views.node(results, 'bus_electricity_') my_results = electricity_bus['sequences'].sum(axis=0).to_dict() storage = es.groups['storage_electricity_battery'] storage_node = views.node(results, storage) my_results['max_load'] = storage_node['sequences'].max()[(( storage, None), 'storage_content')] commodity_bus = views.node(results, 'bus_natural_gas_None') gas_usage = commodity_bus['sequences'][(('source_natural_gas_commodity', 'bus_natural_gas_None'), 'flow')] my_results['gas_usage'] = gas_usage.sum() stor_invest_dict = { 'gas_usage': 1304112, 'max_load': 0, (('bus_electricity_', 'sink_electricity_demand'), 'flow'): 8239764, (('bus_electricity_', 'sink_electricity_excess'), 'flow'): 22036732, (('bus_electricity_', 'storage_electricity_battery'), 'flow'): 0, (('pp_electricity_natural_gas', 'bus_electricity_'), 'flow'): 756385, (('renewable_electricity_pv', 'bus_electricity_'), 'flow'): 744132, (('renewable_electricity_wind', 'bus_electricity_'), 'flow'): 28775978, (( 'storage_electricity_battery', 'bus_electricity_', ), 'flow'): 0 } for key in stor_invest_dict.keys(): eq_(int(round(my_results[key])), int(round(stor_invest_dict[key]))) # Solver results eq_(str(meta['solver']['Termination condition']), 'optimal') eq_(meta['solver']['Error rc'], 0) eq_(str(meta['solver']['Status']), 'ok') # Problem results eq_(int(meta['problem']['Lower bound']), 37819254) eq_(int(meta['problem']['Upper bound']), 37819254) eq_(meta['problem']['Number of variables'], 281) eq_(meta['problem']['Number of constraints'], 163) eq_(meta['problem']['Number of nonzeros'], 116) eq_(meta['problem']['Number of objectives'], 1) eq_(str(meta['problem']['Sense']), 'minimize') # Objective function eq_(round(meta['objective']), 37819254)