def run_test_example(): date_time_index = pd.date_range('1/1/2012', periods=5, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) bgas = solph.Bus(label="natural_gas") bel = solph.Bus(label="electricity") solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) solph.Source(label='rgas', outputs={bgas: solph.Flow()}) solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=[10, 20, 30, 40, 50], fixed=True, nominal_value=1) }) solph.LinearTransformer( label="pp_gas", inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) om = solph.OperationalModel(energysystem) # check solvers solver = dict() for s in ['cbc', 'glpk', 'gurobi', 'cplex']: try: om.solve(solver=s) solver[s] = "working" except Exception: solver[s] = "not working" print("*********") print('Solver installed with oemof:') for s, t in solver.items(): print("{0}: {1}".format(s, t)) print("*********") print("oemof successfully installed.")
def optimise_storage_size(filename="storage_invest.csv", solvername='cbc', debug=True, number_timesteps=8760, tee_switch=True): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/' + str(year), periods=number_timesteps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") data_demand = data['demand_el'] / data['demand_el'].sum() ########################################################################## # Create oemof object ########################################################################## consumption = 5165 * 1e6 wind_installed = 1516 * 1e3 pv_installed = 1491 * 1e3 grid_share = 0.75 logging.info('Create oemof objects') # create gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # create excess component for the electricity bus to allow overproduction solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) # Create commodity object for import electricity resource solph.Source(label='gridsource', outputs={ bel: solph.Flow(nominal_value=consumption * grid_share * number_timesteps / 8760, summed_max=1) }) # create fixed source object for wind solph.Source(label='wind', outputs={ bel: solph.Flow(actual_value=wind_feedin, nominal_value=wind_installed, fixed=True, fixed_costs=20) }) # create fixed source object for pv solph.Source(label='pv', outputs={ bel: solph.Flow(actual_value=pv_feedin, nominal_value=pv_installed, fixed=True, fixed_costs=15) }) # create simple sink object for demand solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data_demand, fixed=True, nominal_value=consumption) }) # Calculate ep_costs from capex to compare with old solph capex = 1000 lifetime = 20 wacc = 0.05 epc = capex * (wacc * (1 + wacc)**lifetime) / ((1 + wacc)**lifetime - 1) # create storage transformer object for storage solph.Storage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=0, nominal_input_capacity_ratio=1, nominal_output_capacity_ratio=1, inflow_conversion_factor=1, outflow_conversion_factor=0.8, fixed_costs=35, investment=solph.Investment(ep_costs=epc), ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.OperationalModel(energysystem) if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver=solvername, solve_kwargs={'tee': tee_switch}) return energysystem
def berlin_model(berlin_e_system): """ Parameters ---------- berlin_e_system : solph.EnergySystem Returns ------- """ time_index = berlin_e_system.time_idx p = preferences.Basic() d = preferences.Data() logging.info("Adding objects to the energy system...") # Electricity solph.Bus(label='bus_el') heat_demand = heat.DemandHeat(time_index) heating_systems = [s for s in heat_demand.get().columns if "frac_" in s] remove_string = 'frac_' heat_demand.demand_by('total_loss_pres', heating_systems, d.bt_dict, remove_string, percentage=True) heat_demand.df = heat_demand.dissolve('bezirk', 'demand_by', index=True) heat_demand.df = heat_demand.df.rename( columns={ k: k.replace('frac_', '') for k in heat_demand.df.columns.get_level_values(1) }) for t in p.types: heat_demand.df[t] = ( heat_demand.df[t].multiply( d.sanierungsanteil[t] * d.sanierungsreduktion[t]) + heat_demand.df[t].multiply(1 - d.sanierungsanteil[t])) * 1000 ep = dict() ep['basic'] = pd.read_csv('/home/uwe/e_p.csv', ';') ep['stromanteil'] = pd.read_csv('/home/uwe/stromanteil_e_p.csv', ';') fraction_heating_system_saniert = { 'off-peak_electricity_heating': 0, 'district_heating': 0.6, 'natural_gas_heating': 0.4, 'oil_heating': 0.4, 'coal_stove': 0, 'wp': 1, } fraction_electrical_dhw = { 'off-peak_electricity_heating': 1, 'district_heating': 0.11, 'natural_gas_heating': 0.09, 'oil_heating': 0.58, 'coal_stove': 1, 'wp': 0, } ep_mix = dict() for e in ep.keys(): ep_mix[e] = dict() for b in p.types: ep_mix[e][b] = dict() cols = [x.replace('_int_DHW', '') for x in ep[e].columns] cols = set([x.replace('_el_DHW', '') for x in cols]) cols.remove('gtype') cols.remove('building') cols.remove('heating_system') for h in cols: tmp = dict() for bs in ['saniert', 'unsaniert']: tmp[bs] = dict() for hs in ['saniert', 'unsaniert']: qu = 'gtype=="{0}"'.format(b.upper()) qu += ' and building=="{0}"'.format(bs) qu += ' and heating_system=="{0}"'.format(hs) # Mix internal DHW and electrical DHW ep[e].ix[(ep[e].gtype == b.upper()) & (ep[e].building == bs) & (ep[e].heating_system == hs), h] = (ep[e].query(qu)[h + '_int_DHW'] * (1 - fraction_electrical_dhw[h]) + ep[e].query(qu)[h + '_el_DHW'] * fraction_electrical_dhw[h]) tmp[bs][hs] = ep[e].query(qu)[h] ep_mix[e][b][h] = ( float(tmp['saniert']['saniert']) * d.sanierungsanteil[b] * fraction_heating_system_saniert[h] + float(tmp['saniert']['unsaniert']) * d.sanierungsanteil[b] * (1 - fraction_heating_system_saniert[h]) + float(tmp['unsaniert']['saniert']) * (1 - d.sanierungsanteil[b]) * fraction_heating_system_saniert[h] + float(tmp['unsaniert']['unsaniert']) * (1 - d.sanierungsanteil[b]) * (1 - fraction_heating_system_saniert[h])) add_dict = { 'district_dz': 'district_heating', 'district_z': 'district_heating', 'bhkw': 'district_heating', } for e in ep_mix.keys(): for b in ep_mix[e].keys(): for new_key in add_dict.keys(): ep_mix[e][b][new_key] = ep_mix[e][b][add_dict[new_key]] # Add heating systems sum_wp = 6.42e+10 # Bei 2000 Volllaststunden sum_bhkw = 6.75e+11 # Bei 2000 Volllaststunden # sum_wp = 50e+9 # sum_bhkw = 50e+9 sum_existing = heat_demand.df.sum().sum() reduction = (sum_existing - (sum_wp + sum_bhkw)) / sum_existing frac_mfh = heat_demand.df.mfh.sum().sum() / heat_demand.df.sum().sum() new = { 'efh': { 'wp': sum_wp * (1 - frac_mfh), 'bhkw': sum_bhkw * (1 - frac_mfh) }, 'mfh': { 'wp': sum_wp * frac_mfh, 'bhkw': sum_bhkw * frac_mfh } } heat_demand.df *= reduction # Join some categories ol = d.other_demand.pop('oil_light') oh = d.other_demand.pop('oil_heavy') oo = d.other_demand.pop('oil_other') for c in ['ghd', 'i']: d.other_demand['oil_heating'][c] = ol[c] + oh[c] + oo[c] d.other_demand['natural_gas_heating'][c] += d.other_demand[ 'liquid_gas'][c] d.other_demand.pop('liquid_gas') heat_demand.df.sortlevel(axis='columns', inplace=True) # noinspection PyTypeChecker district_z = heat_demand.df.loc[:, (slice(None), 'district_heating')].multiply( d.fw_verteilung, axis=0).sum() # noinspection PyTypeChecker district_dz = heat_demand.df.loc[:, (slice(None), 'district_heating')].multiply( (1 - d.fw_verteilung), axis=0).sum() dsum = heat_demand.df.sum() for b in ['efh', 'mfh']: dsum[b, 'district_dz'] = district_dz[b]['district_heating'] dsum[b, 'district_z'] = district_z[b]['district_heating'] dsum[b, 'bhkw'] = new[b]['bhkw'] dsum[b, 'wp'] = new[b]['wp'] dsum.drop('district_heating', 0, 'second', True) dsum.sort_index(inplace=True) ew = pd.read_csv('/home/uwe/chiba/RLI/data/stadtnutzung_erweitert.csv')[[ 'ew', 'schluessel_planungsraum' ]] grp = ew.schluessel_planungsraum.astype(str).str[:-8] grp = grp.apply(lambda x: '{0:0>2}'.format(x)) ew = ew.groupby(grp).sum().drop('schluessel_planungsraum', 1) # dhw_profile = pd.read_csv('/home/uwe/dhw_demand.csv') # *ew.sum() * 657 dhw = ew.sum() * 657000 # 657000 Wh pro EW dhw_factor = (dsum.sum().sum() + float(dhw)) / dsum.sum().sum() dsum *= dhw_factor dfull = d.other_demand aux_elec = dict() sum_aux = 0 print(ep_mix) for b in dsum.keys().levels[0]: for h in dsum[b].keys(): dfull.setdefault(h, dict()) aux_elec.setdefault(h, dict()) aux_elec[h][b] = (dsum[b][h] * ep_mix['basic'][b][h] * ep_mix['stromanteil'][b][h] / 100) print("{:.2E}".format(aux_elec[h][b])) sum_aux += aux_elec[h][b] dfull[h][b] = dsum[b][h] * ep_mix['basic'][b][h] - aux_elec[h][b] # print(dfull) # e = 0 # for a in dfull.keys(): # for b in dfull[a].keys(): # if b in ['i']: # print(a, b, dfull[a][b]) # e += dfull[a][b] # print(e) # exit(0) create_objects.heating_systems(berlin_e_system, dfull, aux_elec, p) mylist = list(berlin_e_system.groups.items()) # Add excess and slack for every BUS for k, g in mylist: if isinstance(g, solph.Bus): solph.Sink(label='excess_{0}'.format(k), inputs={g: solph.Flow(variable_costs=9000)}) solph.Source(label='slack_{0}'.format(k), outputs={g: solph.Flow(variable_costs=9000)}) # slacks = ['bus_el', 'bus_district_z', 'bus_district_dz'] # for s in slacks: # obj = berlin_e_system.groups[s] # solph.Source(label='slack_{0}'.format(s), # outputs={obj: solph.Flow(variable_costs=9000)}) # sources source_costs = { 'lignite': 90, 'natural_gas': 120, 'fuel_bio': 150, 'solar_thermal': 0, 'biomass': 140, 'oil': 130, 'coal': 100 } for src in source_costs: if 'bus_' + src in berlin_e_system.groups: solph.Source(label=src, outputs={ berlin_e_system.groups['bus_' + src]: solph.Flow(variable_costs=source_costs[src]) }) else: logging.warning("No need for a {0} source.".format(src)) # import pprint as pp # pp.pprint(berlin_e_system.groups) logging.info('Optimise the energy system') om = solph.OperationalModel(berlin_e_system) filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver='gurobi', solve_kwargs={'tee': True}) berlin_e_system.dump('/home/uwe/') return berlin_e_system
def optimise_storage_size(filename="storage_investment.csv", solver='cbc', debug=True, number_timesteps=8760, tee_switch=True): logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=number_timesteps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # Read data file full_filename = os.path.join(os.path.dirname(__file__), filename) data = pd.read_csv(full_filename, sep=",") ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") # create excess component for the electricity bus to allow overproduction solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) # create source object representing the natural gas commodity (annual limit) solph.Source(label='rgas', outputs={ bgas: solph.Flow(nominal_value=194397000 * number_timesteps / 8760, summed_max=1) }) # create fixed source object representing wind power plants solph.Source(label='wind', outputs={ bel: solph.Flow(actual_value=data['wind'], nominal_value=1000000, fixed=True, fixed_costs=20) }) # create fixed source object representing pv power plants solph.Source(label='pv', outputs={ bel: solph.Flow(actual_value=data['pv'], nominal_value=582000, fixed=True, fixed_costs=15) }) # create simple sink object representing the electrical demand solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) # create simple transformer object representing a gas power plant solph.LinearTransformer( label="pp_gas", inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) # If the period is one year the equivalent periodical costs (epc) of an # investment are equal to the annuity. Use oemof's economic tools. epc = economics.annuity(capex=1000, n=20, wacc=0.05) # create storage object representing a battery solph.Storage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=0, nominal_input_capacity_ratio=1 / 6, nominal_output_capacity_ratio=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, fixed_costs=35, investment=solph.Investment(ep_costs=epc), ) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') # initialise the operational model om = solph.OperationalModel(energysystem) # if debug is true an lp-file will be written if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'storage_invest.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') om.solve(solver=solver, solve_kwargs={'tee': tee_switch}) return energysystem
def optimise_storage_size(energysystem, filename="variable_chp.csv", solver='cbc', debug=True, tee_switch=True): # 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='rgas', outputs={bgas: solph.Flow(variable_costs=50)}) # create two electricity buses and two heat buses bel = solph.Bus(label="electricity") bel2 = solph.Bus(label="electricity_2") bth = solph.Bus(label="heat") 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_therm', inputs={bth: solph.Flow()}) solph.Sink(label='excess_bel_2', inputs={bel2: solph.Flow()}) solph.Sink(label='excess_elec', inputs={bel: solph.Flow()}) # create simple sink object for electrical demand for each electrical bus solph.Sink(label='demand_elec', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) solph.Sink(label='demand_el_2', inputs={ bel2: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) # create simple sink object for heat demand for each thermal bus solph.Sink(label='demand_therm', inputs={ bth: solph.Flow(actual_value=data['demand_th'], fixed=True, nominal_value=741000) }) solph.Sink(label='demand_th_2', inputs={ bth2: solph.Flow(actual_value=data['demand_th'], fixed=True, nominal_value=741000) }) # This is just a dummy transformer with a nominal input of zero solph.LinearTransformer(label='fixed_chp_gas', inputs={bgas: solph.Flow(nominal_value=0)}, outputs={ bel: solph.Flow(), bth: solph.Flow() }, conversion_factors={ bel: 0.3, bth: 0.5 }) # create a fixed transformer to distribute to the heat_2 and elec_2 buses solph.LinearTransformer(label='fixed_chp_gas_2', 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.VariableFractionTransformer( 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_single_flow={bel: 0.5}) ########################################################################## # Optimise the energy system and plot the results ########################################################################## logging.info('Optimise the energy system') om = solph.OperationalModel(energysystem) if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'variable_chp.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') om.solve(solver=solver, solve_kwargs={'tee': tee_switch}) return energysystem