def get_cost_dict(PH): cost = { 'pp_oil_1': { 'fix': economics.annuity((500 / 8760) * PH, 20, 0.094), 'var': 1.2, 'o&m': 0.02 }, 'pp_oil_2': { 'fix': economics.annuity((500 / 8760) * PH, 20, 0.094), 'var': 1.2, 'o&m': 0.02 }, 'pp_oil_3': { 'fix': economics.annuity((500 / 8760) * PH, 20, 0.094), 'var': 1.2, 'o&m': 0.02 }, 'storage': { 'fix': (3.88 / 8760) * PH, 'var': 0.087, 'epc': economics.annuity((300 / 8760) * PH, 10, 0.094) }, 'pv': { 'fix': (25 / 8760) * PH, 'var': 0, 'epc': economics.annuity((2500 / 8760) * PH, 20, 0.094) } } return cost
def get_ep_cost(df): overnight_cost = df['overnight_cost'] lifetime = df['lifetime'] wacc = df['wacc'] fix_om = df['fix_om'] ep_cost = annuity(overnight_cost, lifetime, wacc) \ + overnight_cost * fix_om return ep_cost
def calc_annuity(cfg, tech_assumptions): """Calculate equivalent annual cost""" tech_assumptions['annuity'] = tech_assumptions.replace(0, nan).apply( lambda row: annuity(row['capex'], row['lifespan'], row['wacc']), axis=1) return tech_assumptions
def get_cost_dict(PH): """ The function calculates the cost in relation to the length of PH cost of the components and returns a cost dictionary :param PH: :return: cost dict """ cost = {'pp_oil_1': {'fix': economics.annuity( (500 / 8760) * PH, 20, 0.094 ), 'var': 1.2, 'o&m': 0.02}, 'pp_oil_2': {'fix': economics.annuity( (500 / 8760) * PH, 20, 0.094 ), 'var': 1.2, 'o&m': 0.02}, 'pp_oil_3': {'fix': economics.annuity( (500 / 8760) * PH, 20, 0.094 ), 'var': 1.2, 'o&m': 0.02}, 'storage': {'fix': (3.88 / 8760) * PH, 'var': 0.087, 'epc': economics.annuity( (300 / 8760) * PH, 10, 0.094 )}, 'pv': {'fix': (25 / 8760) * PH, 'var': 0, 'epc': economics.annuity( (2500 / 8760) * PH, 20, 0.094 )} } return cost
def add_storage(it, labels, gd, nodes, busd): for i, s in it.iterrows(): if s['active']: label_storage = oh.Label(labels['l_1'], s['bus'], s['label'], labels['l_4']) label_bus = busd[(labels['l_1'], s['bus'], 'bus', labels['l_4'])] if s['invest']: epc_s = economics.annuity(capex=s['capex'], n=s['n'], wacc=gd['rate']) * gd['f_invest'] nodes.append( solph.components.GenericStorage( label=label_storage, inputs={label_bus: solph.Flow()}, outputs={label_bus: solph.Flow()}, loss_rate=s['capacity_loss'], invest_relation_input_capacity=s[ 'invest_relation_input_capacity'], invest_relation_output_capacity=s[ 'invest_relation_output_capacity'], inflow_conversion_factor=s['inflow_conversion_factor'], outflow_conversion_factor=s[ 'outflow_conversion_factor'], investment=solph.Investment(ep_costs=epc_s))) else: nodes.append( solph.components.GenericStorage( label=label_storage, inputs={label_bus: solph.Flow()}, outputs={label_bus: solph.Flow()}, loss_rate=s['capacity_loss'], nominal_capacity=s['capacity'], inflow_conversion_factor=s['inflow_conversion_factor'], outflow_conversion_factor=s[ 'outflow_conversion_factor'])) return nodes, busd
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 ep_costs_func(capex, n, opex, wacc): ep_costs = economics.annuity(capex, n, wacc) + capex * opex return ep_costs
def test_optimise_storage_size(filename="storage_investment.csv", solver='cbc'): global PP_GAS logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2012', periods=400, 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="natural_gas") bel = solph.Bus(label="electricity") # Sinks solph.Sink(label='excess_bel', inputs={bel: solph.Flow()}) solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) # Sources solph.Source(label='rgas', outputs={ bgas: solph.Flow(nominal_value=194397000 * 400 / 8760, summed_max=1) }) solph.Source(label='wind', outputs={ bel: solph.Flow(actual_value=data['wind'], nominal_value=1000000, fixed=True) }) solph.Source(label='pv', outputs={ bel: solph.Flow(actual_value=data['pv'], nominal_value=582000, fixed=True) }) # Transformer PP_GAS = solph.Transformer( label='pp_gas', inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) # Investment storage epc = economics.annuity(capex=1000, n=20, wacc=0.05) solph.components.GenericStorage( label='storage', 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, investment=solph.Investment(ep_costs=epc, existing=6851), ) # Solve model om = solph.Model(energysystem) om.receive_duals() om.solve(solver=solver) energysystem.results['main'] = processing.results(om) energysystem.results['meta'] = processing.meta_results(om) # Check dump and restore energysystem.dump()
def display_results(config_path, team_number): ########################################################################### # Load configuration file and parameter data ########################################################################### with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.CLoader) abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) # Get values of energy system parameters file_name_param_01 = cfg['design_parameters_file_name'][team_number] file_name_param_02 = cfg['parameters_file_name'] file_path_param_01 = (abs_path + '/data/' + file_name_param_01) file_path_param_02 = (abs_path + '/data/' + file_name_param_02) 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'] ########################################################################### # Restore results from latest optimisation ########################################################################### energysystem = solph.EnergySystem() abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) energysystem.restore( dpath=abs_path + "/results/optimisation_results/dumps", filename="model_team_{0}.oemof".format(team_number + 1)) string_results = outputlib.views.convert_keys_to_strings( energysystem.results['main']) # Extract specific time series (sequences) from results data shortage_electricity = string_results['shortage_bel', 'electricity']['sequences'] shortage_heat = string_results['shortage_bth', 'heat']['sequences'] gas_consumption = string_results['rgas', 'natural_gas']['sequences'] heat_demand = string_results['heat', 'demand_th']['sequences'] el_demand = string_results['electricity', 'demand_el']['sequences'] print("") print("-- Results (Team", cfg['team_names'][team_number].upper(), ") --") ########################################################################### # CO2-Emissions ########################################################################### em_co2 = (gas_consumption.flow.sum() * param_value['emission_gas'] + shortage_electricity.flow.sum() * param_value['emission_el'] + shortage_heat.flow.sum() * param_value['emission_heat'] ) # [(MWh/a)*(kg/MWh)] print("CO2-Emission: {:.2f}".format(em_co2 / 1e3), "t/a") ########################################################################### # Costs ########################################################################### capex_chp = (param_value['number_of_chps'] * param_value['invest_cost_chp']) capex_boiler = (param_value['number_of_boilers'] * param_value['invest_cost_boiler']) capex_wind = (param_value['number_of_windturbines'] * param_value['invest_cost_wind']) capex_hp = (param_value['number_of_heat_pumps'] * param_value['invest_cost_heatpump']) capex_storage_el = (param_value['capacity_electr_storage'] * param_value['invest_cost_storage_el']) capex_storage_th = (param_value['capacity_thermal_storage'] * param_value['invest_cost_storage_th']) capex_pv = param_value['area_PV'] * param_value['invest_cost_pv'] capex_solarthermal = (param_value['area_solar_th'] * param_value['invest_cost_solarthermal']) capex_PV_pp = (param_value['number_of_PV_pp'] * param_value['invest_cost_PV_pp'] * param_value['PV_pp_surface_area']) # Calculate annuity of each technology annuity_chp = eco.annuity(capex_chp, param_value['lifetime'], param_value['wacc']) annuity_boiler = eco.annuity(capex_boiler, param_value['lifetime'], param_value['wacc']) annuity_wind = eco.annuity(capex_wind, param_value['lifetime'], param_value['wacc']) annuity_hp = eco.annuity(capex_hp, param_value['lifetime'], param_value['wacc']) annuity_storage_el = eco.annuity(capex_storage_el, param_value['lifetime'], param_value['wacc']) annuity_storage_th = eco.annuity(capex_storage_th, param_value['lifetime'], param_value['wacc']) annuity_pv = eco.annuity(capex_pv, param_value['lifetime'], param_value['wacc']) annuity_solar_th = eco.annuity(capex_solarthermal, param_value['lifetime'], param_value['wacc']) annuity_PV_pp = eco.annuity(capex_PV_pp, param_value['lifetime'], param_value['wacc']) # Variable costs var_costs_gas = gas_consumption.flow.sum() * param_value['var_costs_gas'] var_costs_el_import = (shortage_electricity.flow.sum() * param_value['var_costs_shortage_bel']) var_costs_heat_import = (shortage_heat.flow.sum() * param_value['var_costs_shortage_bth']) var_costs_es = var_costs_gas + var_costs_el_import + var_costs_heat_import total_annuity = (annuity_chp + annuity_boiler + annuity_wind + annuity_hp + annuity_storage_el + annuity_storage_th + annuity_pv + annuity_solar_th + annuity_PV_pp) print( "Total Costs of Energy System per Year: {:.2f}".format( (var_costs_es + total_annuity) / 1e6), "Mio. €/a") ########################################################################### # Self-Sufficiency ########################################################################### # Take electrical consumption of heat pump (hp) into account. Quantity of # 'el_demand' does not include electrical consumption of hp. if param_value['number_of_heat_pumps'] > 0: el_consumption_hp = string_results[ 'electricity', 'heat_pump']['sequences'].flow.sum() el_consumption_incl_heatpump = el_demand.flow.sum() + el_consumption_hp coverage_el = ( (el_consumption_incl_heatpump - shortage_electricity.flow.sum()) / el_consumption_incl_heatpump) else: coverage_el = ( (el_demand.flow.sum() - shortage_electricity.flow.sum()) / el_demand.flow.sum()) coverage_heat = ((heat_demand.flow.sum() - shortage_heat.flow.sum()) / heat_demand.flow.sum()) selfsufficiency = (coverage_el + coverage_heat) / 2 print("Self-Sufficiency: {:.2f} %".format(selfsufficiency * 100)) print("") return
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
#Brandenburg energysystem.add(solph.Source(label='rBBGAS_IMPORT', outputs={BBNaturalGas: solph.Flow()})) energysystem.add(solph.Source(label='rBBHCO_IMPORT', outputs={BBHardCoal: solph.Flow()})) energysystem.add(solph.Source(label='rBBLIG_IMPORT', outputs={BBLignite: solph.Flow()})) energysystem.add(solph.Source(label='rBBOIL_IMPORT', outputs={BBOil: solph.Flow()})) energysystem.add(solph.Source(label='rBBBIO_IMPORT', outputs={BBBiomass: solph.Flow()})) #Berlin energysystem.add(solph.Source(label='rBEGAS_IMPORT', outputs={BENaturalGas: solph.Flow()})) energysystem.add(solph.Source(label='rBEHCO_IMPORT', outputs={BEHardCoal: solph.Flow()})) energysystem.add(solph.Source(label='rBELIG_IMPORT', outputs={BELignite: solph.Flow()})) energysystem.add(solph.Source(label='rBEOIL_IMPORT', outputs={BEOil: solph.Flow()})) energysystem.add(solph.Source(label='rBEBIO_IMPORT', outputs={BEBiomass: solph.Flow()})) ## economic investment costs #Brandenburg epc_BBNGA_P = economics.annuity(capex=600000, n=30, wacc=0.07) epc_BBHCO_P = economics.annuity(capex=1800000, n=40, wacc=0.07) epc_BBLIG_P = economics.annuity(capex=1800000, n=40, wacc=0.07) epc_BBOIL_P = economics.annuity(capex=950000, n=30, wacc=0.07) epc_BBBIO_P = economics.annuity(capex=3700000, n=30, wacc=0.07) epc_BBSOLPV_P = economics.annuity(capex=1460000, n=25, wacc=0.07) epc_BBWIND_P = economics.annuity(capex=1330000, n=25, wacc=0.07) epc_BBRORHYD_P = economics.annuity(capex=2925000, n=30, wacc=0.07) #Berlin epc_BENGA_P = economics.annuity(capex=600000, n=30, wacc=0.07) epc_BEHCO_P = economics.annuity(capex=1800000, n=40, wacc=0.07) epc_BELIG_P = economics.annuity(capex=1800000, n=40, wacc=0.07) epc_BEOIL_P = economics.annuity(capex=950000, n=30, wacc=0.07) epc_BEBIO_P = economics.annuity(capex=6700000, n=30, wacc=0.07) epc_BESOLPV_P = economics.annuity(capex=1340000, n=25, wacc=0.07) epc_BEWIND_P = economics.annuity(capex=1330000, n=25, wacc=0.07)
def run_model_dessau(config_path, results_dir): r""" Create the energy system and run the optimisation model. Parameters ---------- config_path : Path to experiment config results_dir : Directory for results Returns ------- energysystem.results : Dict containing results """ abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile) # load input parameter in_param = pd.read_csv(os.path.join(abs_path, cfg['input_parameter']), index_col=[1, 2])['var_value'] wacc = in_param['general', 'wacc'] # load timeseries demand_heat_timeseries = pd.read_csv(os.path.join(results_dir, cfg['timeseries']['timeseries_demand_heat']), index_col=0, names=['demand_heat'], sep=',')['demand_heat'] print(demand_heat_timeseries.head()) # create timeindex if cfg['debug']: number_timesteps = 200 else: number_timesteps = 8760 date_time_index = pd.date_range('1/1/2017', periods=number_timesteps, freq='H') logging.info('Initialize the energy system') energysystem = solph.EnergySystem(timeindex=date_time_index) ##################################################################### logging.info('Create oemof objects') ##################################################################### bgas = solph.Bus(label="natural_gas", balanced=False) bel = solph.Bus(label="electricity", balanced=False) bth_prim = solph.Bus(label="heat_prim") bth_sec = solph.Bus(label="heat_sec") bth_end = solph.Bus(label="heat_end") energysystem.add(bgas, bth_prim, bth_sec, bth_end, bel) # energysystem.add(solph.Sink(label='excess_heat', # inputs={bth: solph.Flow()})) energysystem.add(solph.Source(label='shortage_heat', outputs={bth_prim: solph.Flow(variable_costs=in_param['shortage_heat','var_costs'])})) # energysystem.add(solph.Source(label='rgas', # outputs={bgas: solph.Flow( # variable_costs=0)})) if cfg['investment']['invest_chp']: energysystem.add(solph.Transformer( label='ccgt', inputs={bgas: solph.Flow(variable_costs=in_param['bgas','price_gas'])}, outputs={bth_prim: solph.Flow( investment=solph.Investment( ep_costs=economics.annuity( capex=in_param['ccgt','capex'], n=in_param['ccgt','inv_period'], wacc=wacc)), variable_costs=0)}, conversion_factors={bth_prim: 0.5})) else: energysystem.add(solph.Transformer( label='ccgt', inputs={bgas: solph.Flow(variable_costs=in_param['bgas','price_gas'])}, outputs={bth_prim: solph.Flow( nominal_value=in_param['ccgt','nominal_value'], variable_costs=0)}, conversion_factors={bth_prim: 0.5})) if cfg['investment']['invest_pth']: energysystem.add(solph.Transformer( label='power_to_heat', inputs={bel: solph.Flow(variable_costs=in_param['bel','price_el'])}, outputs={bth_prim: solph.Flow( investment=solph.Investment( ep_costs=economics.annuity( capex=in_param['power_to_heat','capex'], n=in_param['power_to_heat','inv_period'], wacc=wacc)), variable_costs=0)}, conversion_factors={bth_prim: 1})) else: energysystem.add(solph.Transformer(label='power_to_heat', inputs={bel: solph.Flow(variable_costs=in_param['bel','price_el'])}, outputs={bth_prim: solph.Flow( nominal_value=in_param['power_to_heat','nominal_value'], variable_costs=0)}, conversion_factors={bth_prim: 1})) energysystem.add(solph.Transformer( label='dhn_prim', inputs={bth_prim: solph.Flow()}, outputs={bth_sec: solph.Flow()}, conversion_factors={bth_sec: 1.})) energysystem.add(solph.Transformer( label='dhn_sec', inputs={bth_sec: solph.Flow()}, outputs={bth_end: solph.Flow()}, conversion_factors={bth_end: 1.})) energysystem.add(solph.Sink( label='demand_heat', inputs={bth_end: solph.Flow( actual_value=demand_heat_timeseries, fixed=True, nominal_value=1., summed_min=1)})) energysystem.add(solph.components.GenericStorage( label='storage_heat', nominal_capacity=in_param['storage_heat','nominal_capacity'], inputs={bth_prim: solph.Flow( variable_costs=0, nominal_value=in_param['storage_heat','input_nominal_value'])}, outputs={bth_prim: solph.Flow( nominal_value=in_param['storage_heat','output_nominal_value'])}, capacity_loss=in_param['storage_heat','capacity_loss'], initial_capacity=in_param['storage_heat','initial_capacity'], capacity_max=in_param['storage_heat','nominal_capacity'], inflow_conversion_factor=1, outflow_conversion_factor=1)) energysystem_graph = graph.create_nx_graph(energysystem) graph_file_name = os.path.join(results_dir, 'energysystem_graph.pkl') nx.readwrite.write_gpickle(G=energysystem_graph, path=graph_file_name) ##################################################################### logging.info('Solve the optimization problem') om = solph.Model(energysystem) om.solve(solver=cfg['solver'], solve_kwargs={'tee': True}) if cfg['debug']: filename = os.path.join( oemof.tools.helpers.extend_basic_path('lp_files'), 'app_district_heating.lp') logging.info('Store lp-file in {0}.'.format(filename)) om.write(filename, io_options={'symbolic_solver_labels': True}) ##################################################################### logging.info('Check the results') ##################################################################### energysystem.results['main'] = processing.results(om) energysystem.results['meta'] = processing.meta_results(om) energysystem.results['param'] = processing.parameter_as_dict(om) energysystem.dump(dpath=results_dir + '/optimisation_results', filename='es.dump') return energysystem.results
def create_nodes(self, nodes=None): # Create a special dictionary that will raise an error if a key is # updated. This avoids the nodes = tools.NodeDict() # Create global fuel sources ng_bus_label = "bus_natural_gas" nodes[ng_bus_label] = solph.Bus(label=ng_bus_label) ng_cs_label = 'source_natural_gas_' nodes[ng_cs_label] = solph.Source( label=ng_cs_label, outputs={ nodes[ng_bus_label]: solph.Flow( variable_costs=self.table_collection['fuel'].loc[ 'Natural gas', 'cost'], emission=self.table_collection['fuel'].loc['Natural gas', 'cost']) }) uranium_bus_label = "bus_uranium" nodes[uranium_bus_label] = solph.Bus(label=uranium_bus_label) uranium_cs_label = 'source_uranium_' nodes[uranium_cs_label] = solph.Source( label=uranium_cs_label, outputs={ nodes[uranium_bus_label]: solph.Flow( variable_costs=self.table_collection['fuel'].loc['Uranium', 'cost'], emission=self.table_collection['fuel'].loc['Uranium', 'cost']) }) coal_bus_label = "bus_coal" nodes[coal_bus_label] = solph.Bus(label=coal_bus_label) coal_cs_label = 'source_coal_' nodes[coal_cs_label] = solph.Source( label=coal_cs_label, outputs={ nodes[coal_bus_label]: solph.Flow( variable_costs=self.table_collection['fuel'].loc['Coal', 'cost'], emission=self.table_collection['fuel'].loc[ 'Coal', 'co2_emissions']) }) capacity = self.table_collection['transformer_capacity'].groupby( ['region', 'technology']).sum() global_fuel_buses = { 'Coal': coal_bus_label, 'CCGT': ng_bus_label, 'OCGT': ng_bus_label, 'Nuclear': uranium_bus_label } # Create energy system for each region for region in self.table_collection['demand'].columns: region_label = region.replace(" ", '_') # Create electricity bus el_bus_label = "bus_el_{}".format(region_label) nodes[el_bus_label] = solph.Bus(label=el_bus_label) # Create conventional power plants parameter_capacity = self.table_collection['power_plants'].loc[ CONV_PP].join(capacity.loc[region, 'capacity']) for idx, row in parameter_capacity.iterrows(): try: max_capacity = float( self.table_collection['max_capacity'].loc[region, idx]) except: max_capacity = None conv_label = '{0}_{1}'.format(idx.replace(' ', '_'), region_label) nodes[conv_label] = solph.Transformer( label=conv_label, inputs={nodes[global_fuel_buses[idx]]: solph.Flow()}, outputs={ nodes[el_bus_label]: solph.Flow( variable_cost=row['opex_var'], investment=solph.Investment( ep_costs=economics.annuity(capex=row['capex'], n=row['lifetime'], wacc=row['wacc']) + row['opex_fix'], existing=row['capacity'], maximum=max_capacity)) }, conversion_factors={ nodes[el_bus_label]: row['efficiency'] }) # Create RES power plants all_res_params = self.table_collection['power_plants'].loc[ self.table_collection['feedin'].columns].join( capacity.loc[region, 'capacity']) for col in ['PV', 'Wind']: res_label = '{0}_{1}'.format(col, region_label) res_params = all_res_params.loc[col] nodes[res_label] = solph.Source( label=res_label, outputs={ nodes[el_bus_label]: solph.Flow( actual_value=self.table_collection['feedin'].loc[ region, col], fixed=True, variable_cost=res_params['opex_var'], investment=solph.Investment( ep_costs=economics.annuity( capex=res_params['capex'], n=res_params['lifetime'], wacc=res_params['wacc']) + res_params['opex_fix'], existing=res_params['capacity'])) }) for col in ['Hydro']: res_label = '{0}_{1}'.format(col, region_label) res_params = all_res_params.loc[col] nodes[res_label] = solph.Source( label=res_label, outputs={ nodes[el_bus_label]: solph.Flow( actual_value=self.table_collection['feedin'].loc[ region, col], fixed=True, variable_cost=res_params['opex_var'], investment=solph.Investment( ep_costs=economics.annuity( capex=res_params['capex'], n=res_params['lifetime'], wacc=res_params['wacc']) + res_params['opex_fix'], existing=res_params['capacity'], maximum=float( self.table_collection['max_capacity'].loc[ region, 'Hydro']))) }) # Connect demand demand_label = "demand_{}".format(region_label) nodes[demand_label] = solph.Sink( label=demand_label, inputs={ nodes[el_bus_label]: solph.Flow( actual_value=self.table_collection['demand'][region], fixed=True, nominal_value=1) }) # Connect storages # Add excess term to balance curtailment excess_label = 'excess_{}'.format(region_label) nodes[excess_label] = solph.Sink( label=excess_label, inputs={nodes[el_bus_label]: solph.Flow()}) # Add transmission system trm_params = self.table_collection['transmission_params'] length_capacity = self.table_collection[ 'transmission_capacity'].set_index(['from', 'to']).join( self.table_collection['transmission_length'].set_index( ['from', 'to'])).reset_index() for row, pair in length_capacity.iterrows(): lines = [(pair['from'], pair['to']), (pair['to'], pair['from'])] for line in lines: region_1 = line[0].replace(" ", '_') region_2 = line[1].replace(" ", '_') line_label = 'transmission_{0}_{1}'.format(region_1, region_2) bus_label_in = 'bus_el_{0}'.format(region_1) bus_label_out = 'bus_el_{0}'.format(region_2) nodes[line_label] = solph.Transformer( label=line_label, inputs={nodes[bus_label_in]: solph.Flow()}, outputs={ nodes[bus_label_out]: solph.Flow(variable_cost=float(trm_params['opex_var']), investment=solph.Investment( ep_costs=economics.annuity( capex=float(trm_params['capex'] * pair['length']), n=float(trm_params['lifetime']), wacc=float(trm_params['wacc'])) + float(trm_params['opex_fix']), existing=pair['capacity'])) }, conversion_factors={ nodes[bus_label_out]: 1 - float(trm_params['relative_losses_per_1000_km'] * pair['length'] / 1e3) }) # Add emission constraint # Add regional supply constraint return nodes
logger.define_logging() 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__), 'storage_investment.csv') data = pd.read_csv(full_filename, sep=",") price_gas = 0.06 # 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_wind = economics.annuity(capex=1000, n=20, wacc=0.05) epc_pv = economics.annuity(capex=1000, n=20, wacc=0.05) epc_storage = economics.annuity(capex=75, n=20, wacc=0.05) epc_storage_power = economics.annuity(capex=50, n=20, wacc=0.05) ########################################################################## # Create oemof objects ########################################################################## logging.info('Create oemof objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity")
("decentral_heat", "tes"), ] capacity_cost = {} storage_capacity_cost = {} for carrier, tech in ct: capacity_cost[carrier, tech] = ( annuity( float( technologies.loc[ (scenario_year, "capex_power", carrier, tech), "value" ] ), float( technologies.loc[ (scenario_year, "lifetime", carrier, tech), "value" ] ), wacc, ) * 1000, # €/kW -> €/MW )[0] storage_capacity_cost[carrier, tech] = ( annuity( float( technologies.loc[ (scenario_year, "capex_energy", carrier, tech), "value" ]
solph.Sink(label='demand', inputs={ bel: solph.Flow(actual_value=data['demand_el'], fixed=True, nominal_value=1) }) solph.Transformer( label="pp_gas", inputs={bgas: solph.Flow()}, outputs={bel: solph.Flow(nominal_value=10e10, variable_costs=50)}, conversion_factors={bel: 0.58}) epc = economics.annuity(capex=1000, n=20, wacc=0.05) storage = solph.components.GenericStorage( label='storage', inputs={bel: solph.Flow(variable_costs=10e10)}, outputs={bel: solph.Flow(variable_costs=10e10)}, capacity_loss=0.00, initial_capacity=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=epc), ) logging.info('Optimise the energy system')
print("The buses have been created, added, and linked.") # Energy System Components # Onshore Wind es.add( fc.Volatile( label="onshore_NDE", bus=elec_bus_NDE, carrier="wind", tech="onshore", profile=timeseries["onshore-NDE"], expandable=True, capacity=capacity.at["nde_capacity", "onshore"], capacity_cost=(annuity( costs.at["capex", "onshore"], costs.at["lifetime", "onshore"], costs.at["wacc", "onshore"])) + (costs.at["fom", "onshore"]), marginal_cost=(costs.at["vom", "onshore"]) + ((costs.at["carrier_cost", "onshore"]) / (capacity.at["efficiency", "onshore"])), capacity_potential=capacity.at["nde_capacity_potential", "onshore"])) es.add( fc.Volatile( label="onshore_SDE", bus=elec_bus_SDE, carrier="wind", tech="onshore", profile=timeseries["onshore-SDE"], expandable=True, capacity=capacity.at["sde_capacity", "onshore"],
# create excess and shortage to avoid infeasibilies excess = Sink(label='excess_el', inputs={bus_el: Flow()}) shortage = Source(label='shortage_el', outputs={bus_el: Flow(variable_costs=1e12)}) # create demand demand_el = Sink(label='demand_el', inputs={ bus_el: Flow(nominal_value=1, actual_value=data['demand_el'], fixed=True) }) epc_coal = economics.annuity(capex=1500000, n=50, wacc=0.05) epc_gas = economics.annuity(capex=900000, n=20, wacc=0.05) # create power plants pp_coal = Transformer(label='pp_coal', inputs={bus_coal: Flow()}, outputs={ bus_el: Flow(investment=Investment(ep_costs=epc_coal, maximum=5e9, existing=0), variable_costs=25) }, conversion_factors={bus_el: 0.39}) pp_gas = Transformer(label='pp_gas',
def test_annuity(): """Test annuity function of economics tool.""" ok_(round(economics.annuity(1000, 10, 0.1)) == 163) ok_(round(economics.annuity(capex=1000, wacc=0.1, n=10, u=5)) == 264) ok_(round(economics.annuity(1000, 10, 0.1, u=5, cost_decrease=0.1)) == 222)
timeindex = pd.date_range('1/1/2017', periods=8760, freq='H') energysystem = EnergySystem(timeindex=timeindex) Node.registry = energysystem ################################################################# # data ################################################################# # Read data file full_filename = os.path.join(os.path.dirname(__file__), 'timeseries.csv') timeseries = pd.read_csv(full_filename, sep=',') costs = { 'pp_wind': { 'epc': economics.annuity(capex=1000, n=20, wacc=0.05) }, 'pp_pv': { 'epc': economics.annuity(capex=750, n=20, wacc=0.05) }, 'pp_diesel': { 'epc': economics.annuity(capex=300, n=10, wacc=0.05), 'var': 30 }, 'pp_bio': { 'epc': economics.annuity(capex=1000, n=10, wacc=0.05), 'var': 50 }, 'storage': { 'epc': economics.annuity(capex=1500, n=10, wacc=0.05), 'var': 0
logger.define_logging() # create timeindex and load timeseries data date_time_index = pd.date_range('1/1/2012', periods=24*7*8, freq='H') full_filename = os.path.join(os.path.dirname(__file__), 'storage_investment.csv') data = pd.read_csv(full_filename, sep=",") # set parameters params = {'rgas_nom_val': 2000000, 'wind_nom_val': 1000000, 'pv_nom_val': 582000, 'epc_storage': economics.annuity(capex=1000, n=20, wacc=0.05), 'epc_wind': economics.annuity(capex=1000, n=20, wacc=0.05), 'epc_pv': economics.annuity(capex=1000, n=20, wacc=0.05)} def run_model(params, wind_invest=False, pv_invest=False, storage_invest=False): logging.info('Initialize the energy system') energysystem = solph.EnergySystem(timeindex=date_time_index) Node.registry = energysystem logging.info('Create oemof objects') 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(nominal_value=params['rgas_nom_val'],
def display_results(string_results, param_value): # Extract specific time series (sequences) from results data shortage_electricity = string_results['shortage_bel', 'electricity']['sequences'] shortage_heat = string_results['shortage_bth', 'heat']['sequences'] gas_consumption = string_results['rgas', 'natural_gas']['sequences'] heat_demand = string_results['heat', 'demand_th']['sequences'] el_demand = string_results['electricity', 'demand_el']['sequences'] print("") print('-- Results --') #print(shortage_electricity.sum()) #print(shortage_heat.sum()) #print(gas_consumption.sum()) #print(heat_demand.sum()) #print(el_demand.sum()) ########################################################################### # CO2-Emissions ########################################################################### em_co2 = (gas_consumption.flow.sum() * param_value['emission_gas'] + shortage_electricity.flow.sum() * param_value['emission_el'] + shortage_heat.flow.sum() * param_value['emission_heat'] ) # [(MWh/a)*(kg/MWh)] print("CO2-Emission: {:.2f}".format(em_co2 / 1000), "t/a") ########################################################################### # Costs ########################################################################### capex_chp = (param_value['number_of_chps'] * param_value['invest_cost_chp']) capex_boiler = (param_value['number_of_boilers'] * param_value['invest_cost_boiler']) capex_wind = (param_value['number_of_windturbines'] * param_value['invest_cost_wind']) capex_hp = (param_value['number_of_heat_pumps'] * param_value['invest_cost_heatpump']) capex_storage_el = (param_value['capacity_electr_storage'] * param_value['invest_cost_storage_el']) capex_storage_th = (param_value['capacity_thermal_storage'] * param_value['invest_cost_storage_th']) capex_pv_roof = param_value['PV_area_roof'] * param_value['invest_cost_pv'] capex_solarthermal = (param_value['area_solar_th'] * param_value['invest_cost_solarthermal']) capex_pv_field = (param_value['PV_area_field'] * param_value['invest_cost_PV_pp']) # Calculate annuity of each technology annuity_chp = eco.annuity(capex_chp, param_value['lifetime'], param_value['wacc']) annuity_boiler = eco.annuity(capex_boiler, param_value['lifetime'], param_value['wacc']) annuity_wind = eco.annuity(capex_wind, param_value['lifetime'], param_value['wacc']) annuity_hp = eco.annuity(capex_hp, param_value['lifetime'], param_value['wacc']) annuity_storage_el = eco.annuity(capex_storage_el, param_value['lifetime'], param_value['wacc']) annuity_storage_th = eco.annuity(capex_storage_th, param_value['lifetime'], param_value['wacc']) annuity_pv_roof = eco.annuity(capex_pv_roof, param_value['lifetime'], param_value['wacc']) annuity_solar_th = eco.annuity(capex_solarthermal, param_value['lifetime'], param_value['wacc']) annuity_pv_field = eco.annuity(capex_pv_field, param_value['lifetime'], param_value['wacc']) # Variable costs var_costs_gas = gas_consumption.flow.sum() * param_value['var_costs_gas'] var_costs_el_import = (shortage_electricity.flow.sum() * param_value['var_costs_shortage_bel']) var_costs_heat_import = (shortage_heat.flow.sum() * param_value['var_costs_shortage_bth']) var_costs_es = var_costs_gas + var_costs_el_import + var_costs_heat_import total_annuity = (annuity_chp + annuity_boiler + annuity_wind + annuity_hp + annuity_storage_el + annuity_storage_th + annuity_pv_roof + annuity_solar_th + annuity_pv_field) print( "Total Costs of Energy System per Year: {:.2f}".format( (var_costs_es + total_annuity) / 1e6), "Mio. €/a") ########################################################################### # Self-Sufficiency ########################################################################### # Take electrical consumption of heat pump (hp) into account. Quantity of # 'el_demand' does not include electrical consumption of hp. if param_value['number_of_heat_pumps'] > 0: el_consumption_hp = string_results[ 'electricity', 'heat_pump']['sequences'].flow.sum() el_consumption_incl_heatpump = el_demand.flow.sum() + el_consumption_hp coverage_el = ( (el_consumption_incl_heatpump - shortage_electricity.flow.sum()) / el_consumption_incl_heatpump) else: coverage_el = ( (el_demand.flow.sum() - shortage_electricity.flow.sum()) / el_demand.flow.sum()) coverage_heat = ((heat_demand.flow.sum() - shortage_heat.flow.sum()) / heat_demand.flow.sum()) selfsufficiency = (coverage_el + coverage_heat) / 2 print("Self-Sufficiency: {:.2f} %".format(selfsufficiency * 100)) print("") return [(em_co2 / 1e3), ((var_costs_es + total_annuity) / 1e6), (selfsufficiency * 100) ], [(em_co2 / 1e3), (em_co2 / 1e3) + 10000, ((var_costs_es + total_annuity) / 1e6), ((var_costs_es + total_annuity) / 1e6) + 10000, (selfsufficiency * 100), (selfsufficiency * 100) - 100]
plt.savefig( "visualization/figures/investment_cost-report.pdf", bbox_extra_artists=(lgd, ), bbox_inches="tight", ) invest_plot.multiply(1e3).round(2).fillna("-").to_latex( caption="Investment cost in Mio. US $. ", label="tab:investment_cost", buf="visualization/tables/investment_cost-report.tex") from oemof.tools.economics import annuity aut_scenarios = ["AUT"] + ["AUT-" + str(s) for s in range(40, 100, 10)] conv_scenarios = ["CONT"] #+ ["CONT-" + str(s) for s in range(10, 20, 10)] re_scenarios = ["GRE"] + ["GRE-" + str(s) for s in range(40, 100, 10)] base_scenarios = ["BASE"] + ["BASE-" + str(s) for s in range(40, 100, 10)] base_invest = (annuity(800, 20, 0.05) * 1000) * 1.035 * 4293 base_invest = 0 lcoe = pd.DataFrame([ objective[conv_scenarios].add(base_invest).divide(28e6).values[0], objective[base_scenarios].add(base_invest).divide(28e6).values[0], objective[re_scenarios].add(base_invest).divide(28e6).values[0], objective[aut_scenarios].add(base_invest).divide(28e6).values[0] ], index=["CONT", "BASE", "GRE", "AUT"], columns=["REF", "40%", "50%", "60%", "70%", "80%", "90%"]).round(2) ax = lcoe.T.plot(kind="line", marker="o", rot=0, color=sns.xkcd_palette(
def run_model_flexchp(config_path, variation_nr): with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile) if cfg['debug']: number_of_time_steps = 3 else: number_of_time_steps = 8760 solver = cfg['solver'] debug = cfg['debug'] solver_verbose = cfg['solver_verbose'] # show/hide solver output abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) # initiate the logger (see the API docs for more information) logger.define_logging(logpath=(abs_path + '/results/optimisation_results/log/'), logfile=(cfg['filename_logfile']+'_scenario_{0}.log'. format(variation_nr)), screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Use parameters for scenario {0}'.format(variation_nr)) logging.info('Initialize the energy system') date_time_index = pd.date_range(cfg['start_date'], periods=number_of_time_steps, freq=cfg['frequency']) energysystem = solph.EnergySystem(timeindex=date_time_index) ########################################################################## # Read time series and parameter values from data files ########################################################################## file_path_demand_ts = abs_path + cfg['demand_time_series'] data = pd.read_csv(file_path_demand_ts) file_path_param_01 = abs_path + cfg['parameters_energy_system'] file_path_param_02 = abs_path + cfg['parameter_variation'][variation_nr] 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'] ########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') bgas = solph.Bus(label="natural_gas") bel = solph.Bus(label="electricity") bel_residual = solph.Bus(label="residual") bth = solph.Bus(label='heat') energysystem.add(bgas, bel, bel_residual, bth) # Sources and sinks energysystem.add(solph.Sink( label='excess_bel', inputs={bel: solph.Flow( variable_costs=param_value['var_costs_excess_bel'])})) energysystem.add(solph.Sink( label='excess_bth', inputs={bth: solph.Flow( variable_costs=param_value['var_costs_excess_bth'])})) energysystem.add(solph.Source( label='shortage_bel', outputs={bel: solph.Flow( variable_costs=param_value['var_costs_shortage_bel'])})) energysystem.add(solph.Source( label='shortage_bth', outputs={bth: solph.Flow( variable_costs=param_value['var_costs_shortage_bth'])})) energysystem.add(solph.Source( label='rgas', outputs={bgas: solph.Flow( nominal_value=param_value['nom_val_gas'], summed_max=param_value['sum_max_gas'], variable_costs=(param_value['var_costs_gas'] * param_value['gas_price_variation']))})) energysystem.add(solph.Source( label='residual_el', outputs={bel_residual: solph.Flow( actual_value=data['neg_residual_el'], nominal_value=param_value['nom_val_neg_residual'], fixed=True)})) if cfg['price_el_quadratic'] == True: energysystem.add(solph.Sink( label='demand_el', inputs={bel: solph.Flow( variable_costs=(param_value['el_price'] * param_value['price_factor_sqr'] * param_value['el_price_variation'] * data['demand_el']**2), nominal_value=8000)})) if cfg['price_el_quadratic'] == False: energysystem.add(solph.Sink( label='demand_el', inputs={bel: solph.Flow( variable_costs=(param_value['el_price'] * param_value['el_price_variation'] * data['demand_el']), nominal_value=8000)})) energysystem.add(solph.Sink( label='demand_th', inputs={bth: solph.Flow( actual_value=data['demand_th'], nominal_value=param_value['nom_val_demand_th'], fixed=True, variable_costs=(- param_value['var_costs_gas'] / param_value['conversion_factor_boiler']))})) # Auxiliary component to prevent CHP electricity being used in P2H (not # representing a physical component!) energysystem.add(solph.Transformer( label='oneway', inputs={bel_residual: solph.Flow( nominal_value=param_value['nom_val_neg_residual'])}, outputs={bel: solph.Flow()}, conversion_factors={bel: 1})) # Combined Heat and Power Plant (CHP) # Calculate annuity per installed unit of power [€/MW] ep_costs_CHP = economics.annuity( capex=param_value['capex_CHP'], n=param_value['lifetime_CHP'], wacc=param_value['wacc_CHP']) # Add CHP with its technical specifications to the energy system energysystem.add(ExtractionTurbineCHP( label='CHP_01', inputs={bgas: solph.Flow( investment=solph.Investment( ep_costs=(ep_costs_CHP*param_value['conv_factor_full_cond']), maximum=1667))}, outputs={ bel: solph.Flow(), bth: solph.Flow()}, conversion_factors={ bel: param_value['conv_factor_bel_CHP'], bth: param_value['conv_factor_bth_CHP']}, conversion_factor_full_condensation={ bel: param_value['conv_factor_full_cond']})) # Peak load gas boiler # Calculate annuity per installed unit of power [€/MW] ep_costs_boiler = economics.annuity( capex=param_value['capex_boiler'], n=param_value['lifetime_boiler'], wacc=param_value['wacc_boiler']) # Add boiler with its technical specifications to the energy system energysystem.add(solph.Transformer( label='boiler', inputs={bgas: solph.Flow()}, outputs={bth: solph.Flow(investment=solph.Investment( ep_costs=ep_costs_boiler))}, conversion_factors={bth: param_value['conversion_factor_boiler']})) ep_costs_p2h = economics.annuity( capex=param_value['capex_p2h'], n=param_value['lifetime_p2h'], wacc=param_value['wacc_p2h']) energysystem.add(solph.Transformer( label='P2H', inputs={bel_residual: solph.Flow()}, outputs={bth: solph.Flow(investment=solph.Investment( ep_costs=ep_costs_p2h))}, conversion_factors={bth: param_value['conversion_factor_p2h']})) ep_costs_TES = economics.annuity( capex=(param_value['capex_TES']*param_value['TES_capex_variation']), n=param_value['lifetime_TES'], wacc=param_value['wacc_TES']) storage_th = solph.components.GenericStorage( label='storage_th', inputs={bth: solph.Flow()}, outputs={bth: solph.Flow()}, capacity_loss=param_value['capacity_loss_storage_th'], initial_capacity=param_value['init_capacity_storage_th'], inflow_conversion_factor=param_value['inflow_conv_factor_storage_th'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_th'], invest_relation_input_capacity=1/param_value[ 'charging_time_storage_th'], invest_relation_output_capacity=1/param_value[ 'charging_time_storage_th'], investment=solph.Investment(ep_costs=ep_costs_TES)) energysystem.add(storage_th) ep_costs_EES = economics.annuity( capex=param_value['capex_EES']*param_value['EES_capex_variation'], n=param_value['lifetime_EES'], wacc=param_value['wacc_EES']) storage_el = solph.components.GenericStorage( label='storage_el', inputs={bel: solph.Flow()}, outputs={bel: solph.Flow()}, capacity_loss=param_value['capacity_loss_storage_el'], initial_capacity=param_value['init_capacity_storage_el'], inflow_conversion_factor=param_value['inflow_conv_factor_storage_el'], outflow_conversion_factor=param_value[ 'outflow_conv_factor_storage_el'], invest_relation_input_capacity=1 / param_value[ 'charging_time_storage_el'], invest_relation_output_capacity=1 / param_value[ 'charging_time_storage_el'], investment=solph.Investment(ep_costs=ep_costs_EES)) energysystem.add(storage_el) ########################################################################## # Optimise the energy system and store the results ########################################################################## logging.info('Optimise the energy system') model = solph.Model(energysystem) if debug: lpfile_name = 'flexCHP_scenario_{0}.lp'.format(variation_nr) filename = os.path.join( helpers.extend_basic_path('lp_files'), lpfile_name) logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) logging.info('Solve the optimization problem') model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) if cfg['price_el_quadratic']: energysystem.dump( dpath=(abs_path + "/results/optimisation_results/dumps/" "quadratic_price_relationship"), filename=(cfg['filename_dumb']+'_scenario_{0}.oemof'. format(variation_nr))) if cfg['price_el_quadratic'] == False: energysystem.dump( dpath=(abs_path + "/results/optimisation_results/dumps/" "linear_price_relationship"), filename=(cfg['filename_dumb']+'_scenario_{0}.oemof'.format( variation_nr)))
data_precalc['ES_load_actual_entsoe_power_statistics'] = list( dataframe['ES_load_actual_entsoe_power_statistics'].iloc[:periods]) data_precalc.to_csv(os.path.join(results_path, 'results_csp_plant_precalc.csv')) # Regular oemof_system # Parameters for the energy system additional_losses = 0.2 elec_consumption = 0.05 backup_costs = 1000 cap_loss = 0.02 conversion_storage = 0.95 costs_storage = economics.annuity(20, 20, 0.06) costs_electricity = 1000 conversion_factor_turbine = 0.4 size_collector = 1000 # Busses bth = solph.Bus(label='thermal') bel = solph.Bus(label='electricity') bcol = solph.Bus(label='solar') # Sources and sinks col_heat = solph.Source(label='collector_heat', outputs={ bcol: solph.Flow(fix=data_precalc['collector_heat'], nominal_value=size_collector)
def test_economics(): ok_(round(economics.annuity(1000, 10, 0.1)) == 163)
########################################################################## # Create oemof object ########################################################################## logging.info('Create oemof objects') bgas = solph.Bus(label="natural_gas") bel = solph.Bus(label="electricity") bth = solph.Bus(label='heat') energysystem.add(bgas, bel, bth) # Parameters for invest option epc_CHP = economics.annuity(param_value['capex_chp'], param_value['life_time_chp'], param_value['wacc_chp']) epc_storage_th = economics.annuity(param_value['capex_storage_th'], param_value['life_time_storage_th'], param_value['wacc_storage_th']) epc_storage_el = economics.annuity(param_value['capex_storage_el'], param_value['life_time_storage_el'], param_value['wacc_storage_el']) epc_boiler = economics.annuity(param_value['capex_boiler'], param_value['life_time_boiler'], param_value['wacc_boiler']) epc_PtH = economics.annuity(param_value['capex_pth'], param_value['life_time_pth'], param_value['wacc_pth']) # Sources and sinks
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) thermal_collector = solph.Source( label='thermal_collector', outputs={ b_heat: solph.Flow( actual_value=[solar_thermal(day) for day in range(0, periods)], investment=solph.Investment(ep_costs=epc, minimum=1.0, maximum=5.0), fixed=True) }) excess_heat = solph.Sink(label='excess_heat', inputs={b_heat: solph.Flow(nominal_value=10)})
def run_model(config_path, team_number): with open(config_path, 'r') as ymlfile: cfg = yaml.load(ymlfile, Loader=yaml.CLoader) if cfg['debug']: number_of_time_steps = 3 else: number_of_time_steps = 8760 solver = cfg['solver'] debug = cfg['debug'] periods = number_of_time_steps solver_verbose = cfg['solver_verbose'] # show/hide solver output logger.define_logging(logfile='model_team_{0}.log'.format(team_number + 1), screen_level=logging.INFO, file_level=logging.DEBUG) logging.info('Initialize the energy system') date_time_index = pd.date_range('1/1/2019', periods=number_of_time_steps, freq='H') energysystem = solph.EnergySystem(timeindex=date_time_index) # timestr = time.strftime("%Y%m%d") ########################################################################## # Einlesen der Zeitreihen und Variablen aus den Dateien ########################################################################## abs_path = os.path.dirname(os.path.abspath(os.path.join(__file__, '..'))) file_path_ts = abs_path + '/data_raw/' + cfg['time_series_file_name'] data = pd.read_csv(file_path_ts, sep=';') file_name_param_01 = cfg['design_parameters_file_name'][team_number] file_path_param_01 = (abs_path + '/data/' + file_name_param_01) param_df_01 = pd.read_csv(file_path_param_01, index_col=1, sep=';', encoding='unicode_escape') param_value = param_df_01['value'] # periodische Kosten epc_PV = economics.annuity(capex=param_value['capex_PV'], n=param_value['n_PV'], wacc=param_value['wacc']) epc_Solarthermie = economics.annuity(capex=param_value['capex_Sol'], n=param_value['n_Sol'], wacc=param_value['wacc']) epc_gas_boiler = economics.annuity(capex=param_value['capex_Gaskessel'], n=param_value['n_Gaskessel'], wacc=param_value['wacc']) epc_BHKW = economics.annuity(capex=param_value['capex_BHKW'], n=param_value['n_BHKW'], wacc=param_value['wacc']) epc_heat_pump = economics.annuity(capex=param_value['capex_Waermepumpe'], n=param_value['n_Waermepumpe'], wacc=param_value['wacc']) epc_el_storage = economics.annuity( capex=param_value['capex_Stromspeicher'], n=param_value['n_Stromspeicher'], wacc=param_value['wacc']) epc_th_storage = economics.annuity( capex=param_value['capex_Waermespeicher'], n=param_value['n_Waermespeicher'], wacc=param_value['wacc']) ########################################################################## # Erstellung der Oemof-Komponenten ########################################################################## logging.info('Create oemof objects') ### Definition der bus'es ################################################# # Erdgasbus b_gas = solph.Bus(label="Erdgas") # Strombus b_el = solph.Bus(label="Strom") # Waermebus b_th = solph.Bus(label="Waerme") # Hinzufügen zum Energiesystem energysystem.add(b_gas, b_el, b_th) ### Definition des Ueberschusses ######################################### # Senke fuer Stromueberschusss energysystem.add( solph.Sink(label='excess_bel', inputs={b_el: solph.Flow()})) # Senke fuer Waermeueberschuss energysystem.add( solph.Sink(label='excess_bth', inputs={b_th: solph.Flow()})) ### Definition Quellen ################################################# # Quelle: Erdgasnetz energysystem.add( solph.Source(label='Gasnetz', outputs={ b_gas: solph.Flow(variable_costs=param_value['vc_gas'] + param_value['vc_CO2']) })) #[€/kWh] # Quelle: Stromnetz energysystem.add( solph.Source(label='Strombezug', outputs={ b_el: solph.Flow(variable_costs=param_value['vc_el']) })) #[€/kWh] # Quelle: Waermenetz/Fernwaerme energysystem.add( solph.Source(label='Waermebezug', outputs={ b_th: solph.Flow(variable_costs=param_value['vc_th']) })) #[€/kWh] # Quelle: Solaranlage if param_value['A_Kollektor_gesamt'] > 0: energysystem.add( solph.Source( label='PV', outputs={ b_el: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.001 * param_value['cf_PV']), #[kWh/m²] fixed=True, investment=solph.Investment( ep_costs=epc_PV, minimum=param_value['A_min_PV'] * 1 * param_value['cf_PV'])) })) # Quelle: Solarthermieanlage if param_value['A_Kollektor_gesamt'] > 0: energysystem.add( solph.Source( label='Solarthermie', outputs={ b_th: solph.Flow( actual_value=(data['Sol_irradiation [Wh/sqm]'] * 0.001 * param_value['cf_Sol']), #[kWh/m²] fixed=True, investment=solph.Investment( ep_costs=epc_Solarthermie, minimum=param_value['A_min_Sol'] * 1 * param_value['cf_Sol'])) })) ### Definition Bedarf ################################################ # Strombedarf energysystem.add( solph.Sink( label='Strombedarf', inputs={ b_el: solph.Flow( actual_value=data['P*'], nominal_value=param_value['W_el'], #[kWh] fixed=True) })) # Waermebedarf energysystem.add( solph.Sink( label='Waermebedarf', inputs={ b_th: solph.Flow( actual_value=data['Q*'], nominal_value=param_value['W_th'], #[kWh] fixed=True) })) ### Definition Systemkomponenten ######################################### # Transformer: Gaskessel if param_value['max_Gaskessel'] > 0: energysystem.add( solph.Transformer( label="Gaskessel", inputs={b_gas: solph.Flow()}, outputs={ b_th: solph.Flow(investment=solph.Investment( ep_costs=epc_gas_boiler, minimum=param_value['min_Gaskessel'], #[kW] maximum=param_value['max_Gaskessel'])) }, #[kW] conversion_factors={b_th: param_value['cf_Gaskessel']})) # Transformer: BHKW if param_value['max_BHKW'] > 0: energysystem.add( solph.Transformer( label="BHKW", inputs={b_gas: solph.Flow()}, outputs={ b_el: solph.Flow(), b_th: solph.Flow(investment=solph.Investment( ep_costs=epc_BHKW, minimum=param_value['min_BHKW'], #[kW] maximum=param_value['max_BHKW'])) }, #[kW] conversion_factors={ b_el: param_value['cf_BHKW_el'], b_th: 0.85 - param_value['cf_BHKW_el'] })) # Transformer: Waermepumpe if param_value['max_Waermepumpe'] > 0: energysystem.add( solph.Transformer( label="Waermepumpe", inputs={b_el: solph.Flow()}, outputs={ b_th: solph.Flow(investment=solph.Investment( ep_costs=epc_heat_pump, minimum=param_value['min_Waermepumpe'], #[kW] maximum=param_value['max_Waermepumpe'])) }, #[kW] conversion_factors={b_th: param_value['COP_Waermepumpe']})) # Speicher: Stromspeicher if param_value['max_Stromspeicher'] > 0: Stromspeicher = solph.components.GenericStorage( label='Stromspeicher', inputs={b_el: solph.Flow()}, outputs={b_el: solph.Flow()}, loss_rate=param_value['lr_Stromspeicher'], initial_storage_level=param_value['isl_Stromspeicher'], inflow_conversion_factor=param_value['cf_Stromspeicher_ein'], outflow_conversion_factor=param_value['cf_Stromspeicher_aus'], investment=solph.Investment( ep_costs=epc_el_storage, minimum=param_value['min_Stromspeicher'], #[kWh] maximum=param_value['max_Stromspeicher'])) #[kWh] energysystem.add(Stromspeicher) # Speicher: Waermespeicher if param_value['max_Waermespeicher'] > 0: Waermespeicher = solph.components.GenericStorage( label='Waermespeicher', inputs={b_th: solph.Flow()}, outputs={b_th: solph.Flow()}, loss_rate=param_value['lr_Waermespeicher'], initial_storage_level=param_value['isl_Waermespeicher'], inflow_conversion_factor=param_value['cf_Waermespeicher_ein'], outflow_conversion_factor=param_value['cf_Waermespeicher_aus'], investment=solph.Investment( ep_costs=epc_th_storage, minimum=param_value['min_Waermespeicher'], #[kWh] maximum=param_value['max_Waermespeicher'])) #[kWh] energysystem.add(Waermespeicher) logging.info('Optimise the energy system') # Initialisierung des Modells model = solph.Model(energysystem) ########################################################################## # Constraint fuer Kollektorgesamtflaeche ########################################################################## PV_installed = energysystem.groups['PV'] Sol_installed = energysystem.groups['Solarthermie'] myconstrains = po.Block() model.add_component('MyBlock', myconstrains) myconstrains.collector_area = po.Constraint(expr=( (((model.InvestmentFlow.invest[PV_installed, b_el]) / (1 * param_value['cf_PV'])) + ((model.InvestmentFlow.invest[Sol_installed, b_th]) / (1 * param_value['cf_Sol']))) <= param_value['A_Kollektor_gesamt'])) ########################################################################## # Optimierung des Systems und Speichern des Ergebnisses ########################################################################## if debug: filename = os.path.join(helpers.extend_basic_path('lp_files'), 'model_team_{0}.lp'.format(team_number + 1)) logging.info('Store lp-file in {0}.'.format(filename)) model.write(filename, io_options={'symbolic_solver_labels': True}) # if tee_switch is true solver messages will be displayed logging.info( 'Solve the optimization problem of team {0}'.format(team_number + 1)) model.solve(solver=solver, solve_kwargs={'tee': solver_verbose}) logging.info('Store the energy system with the results.') # add results to the energy system to make it possible to store them. energysystem.results['main'] = outputlib.processing.results(model) energysystem.results['meta'] = outputlib.processing.meta_results(model) results = energysystem.results['main'] energysystem.dump(dpath=abs_path + "/results", filename="model_team_{0}.oemof".format(team_number + 1))
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__), 'storage_investment.csv') data = pd.read_csv(full_filename, sep=",") fossil_share = 0.2 consumption_total = data['demand_el'].sum() # 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_storage = economics.annuity(capex=1000, n=20, wacc=0.05) ########################################################################## # Create oemof objects ########################################################################## logging.info('Create oemof objects') # create natural gas bus bgas = solph.Bus(label="natural_gas") # create electricity bus bel = solph.Bus(label="electricity") energysystem.add(bgas, bel) # create excess component for the electricity bus to allow overproduction
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