from oemof import outputlib from oemof.solph import EnergySystem, Model, Bus, Sink, Source, Transformer, Flow periods = 20 timeindex = pd.date_range(start='2020-01-01', periods=periods, freq='H') x = np.arange(0, periods, 1) demand_ts = 0.5 * np.cos(x) + 1 print(demand_ts) es = EnergySystem(timeindex=timeindex) el_bus = Bus(label='el_bus') demand = Sink( label='el_demand', inputs={ el_bus: Flow( nominal_value=10, actual_value=demand_ts, fixed=True ) } ) pp1 = Source( label='powerplant_1', outputs={
import os import pandas as pd from oemof.solph import (Bus, Sink, Source, Flow, Transformer, Model, EnergySystem) filename = os.path.join(os.path.dirname(__file__), 'input_data.csv') data = pd.read_csv(filename, sep=",") 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 wind = Source(label='wind', outputs={ bel: Flow(actual_value=data['wind'], nominal_value=66.3, fixed=True) })
import matplotlib.pyplot as plt solver = "cbc" # Create an energy system and optimize the dispatch at least costs. # ####################### initialize and provide data ##################### datetimeindex = pd.date_range("1/1/2016", periods=24 * 10, freq="H") energysystem = EnergySystem(timeindex=datetimeindex) filename = os.path.join(os.getcwd(), "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="bel") bth = Bus(label="bth") energysystem.add(bcoal, bgas, boil, blig, bel, bth) # an excess and a shortage variable can help to avoid infeasible problems energysystem.add(Sink(label="excess_el", inputs={bel: Flow()})) # shortage_el = Source(label='shortage_el', # outputs={bel: Flow(variable_costs=200)})
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_add_constraints_example(solver='cbc', nologg=False): if not nologg: logging.basicConfig(level=logging.INFO) # ##### creating an oemof solph optimization model, nothing special here ## # create an energy system object for the oemof solph nodes es = EnergySystem(timeindex=pd.date_range('1/1/2012', periods=4, freq='H')) Node.registry = es # add some nodes boil = Bus(label="oil", balanced=False) blig = Bus(label="lignite", balanced=False) b_el = Bus(label="b_el") Sink(label="Sink", inputs={ b_el: Flow(nominal_value=40, actual_value=[0.5, 0.4, 0.3, 1], fixed=True) }) pp_oil = Transformer( label='pp_oil', inputs={boil: Flow()}, outputs={b_el: Flow(nominal_value=50, variable_costs=25)}, conversion_factors={b_el: 0.39}) Transformer(label='pp_lig', inputs={blig: Flow()}, outputs={b_el: Flow(nominal_value=50, variable_costs=10)}, conversion_factors={b_el: 0.41}) # create the model om = Model(energysystem=es) # add specific emission values to flow objects if source is a commodity bus for s, t in om.flows.keys(): if s is boil: om.flows[s, t].emission_factor = 0.27 # t/MWh if s is blig: om.flows[s, t].emission_factor = 0.39 # t/MWh emission_limit = 60e3 # add the outflow share om.flows[(boil, pp_oil)].outflow_share = [1, 0.5, 0, 0.3] # Now we are going to add a 'sub-model' and add a user specific constraint # first we add ad pyomo Block() instance that we can use to add our # constraints. Then, we add this Block to our previous defined # Model instance and add the constraints. myblock = po.Block() # create a pyomo set with the flows (i.e. list of tuples), # there will of course be only one flow inside this set, the one we used to # add outflow_share myblock.MYFLOWS = po.Set(initialize=[ k for (k, v) in om.flows.items() if hasattr(v, 'outflow_share') ]) # pyomo does not need a po.Set, we can use a simple list as well myblock.COMMODITYFLOWS = [ k for (k, v) in om.flows.items() if hasattr(v, 'emission_factor') ] # add the sub-model to the oemof Model instance om.add_component('MyBlock', myblock) def _inflow_share_rule(m, s, e, t): """pyomo rule definition: Here we can use all objects from the block or the om object, in this case we don't need anything from the block except the newly defined set MYFLOWS. """ expr = (om.flow[s, e, t] >= om.flows[s, e].outflow_share[t] * sum(om.flow[i, o, t] for (i, o) in om.FLOWS if o == e)) return expr myblock.inflow_share = po.Constraint(myblock.MYFLOWS, om.TIMESTEPS, rule=_inflow_share_rule) # add emission constraint myblock.emission_constr = po.Constraint( expr=(sum(om.flow[i, o, t] for (i, o) in myblock.COMMODITYFLOWS for t in om.TIMESTEPS) <= emission_limit)) # solve and write results to dictionary # you may print the model with om.pprint() ok_(om.solve(solver=solver)) logging.info("Successfully finished.")
'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 } } ################################################################# # Create oemof object ################################################################# bel = Bus(label='micro_grid') Sink(label='excess', inputs={bel: Flow(variable_costs=10e3)}) Source(label='pp_wind', outputs={ bel: Flow(nominal_value=None, fixed=True, actual_value=timeseries['wind'], investment=Investment(ep_costs=costs['pp_wind']['epc'])) }) Source(label='pp_pv', outputs={ bel:
# add edge labels for all edges if edge_labels is True and plt: labels = nx.get_edge_attributes(grph, 'weight') nx.draw_networkx_edge_labels(grph, pos=pos, edge_labels=labels) # show output if plot is True: plt.show() datetimeindex = pd.date_range('1/1/2017', periods=2, freq='H') es = EnergySystem(timeindex=datetimeindex) b_0 = Bus(label='b_0') b_1 = Bus(label='b_1') es.add(b_0, b_1) es.add(custom.Link(label="line_0", inputs={ b_0: Flow(), b_1: Flow()}, outputs={ b_1: Flow(investment=Investment()), b_0: Flow(investment=Investment())}, conversion_factors={ (b_0, b_1): 0.95, (b_1, b_0): 0.9}))
screen_level=logging.INFO, file_level=logging.DEBUG) # Creating the energy system date_time_index = pd.date_range('1/1/2018', periods=24 * 365, freq='H') es = EnergySystem(timeindex=date_time_index) filename = 'data_timeseries.csv' data = pd.read_csv(filename, sep=",") logging.info('Energy system created and initialized') # Creating the necessary buses elbus = Bus(label='electricity') logging.info('Necessary buses for the system created') # Now creating the necessary components for the system epc_pv = economics.annuity(capex=1000, n=20, wacc=0.05) epc_storage = economics.annuity(capex=100, n=5, wacc=0.05) pv = Source(label='pv', outputs={ elbus: Flow(actual_value=data['pv'], nominal_value=None, fixed=True, investment=Investment(ep_costs=epc_pv, maximum=30))
print_parameters() # Set up an energy system model solver = 'cbc' periods = 100 datetimeindex = pd.date_range('1/1/2019', periods=periods, freq='H') demand_timeseries = np.zeros(periods) demand_timeseries[-5:] = 1 heat_feedin_timeseries = np.zeros(periods) heat_feedin_timeseries[:10] = 1 energysystem = EnergySystem(timeindex=datetimeindex) bus_heat = Bus(label='bus_heat') heat_source = Source(label='heat_source', outputs={ bus_heat: Flow(nominal_value=1, actual_value=heat_feedin_timeseries, fixed=True) }) shortage = Source(label='shortage', outputs={bus_heat: Flow(variable_costs=1e6)}) excess = Sink(label='excess', inputs={bus_heat: Flow()}) heat_demand = Sink(label='heat_demand',
def test_dispatch_example(solver='cbc', periods=24 * 5): """Create an energy system and optimize the dispatch at least costs.""" 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 wind = Source(label='wind', outputs={ bel: Flow(actual_value=data['wind'], nominal_value=66.3, fixed=True) }) pv = Source(label='pv', outputs={ bel: Flow(actual_value=data['pv'], nominal_value=65.3, fixed=True) }) # demands (electricity/heat) demand_el = Sink(label='demand_elec', inputs={ bel: Flow(nominal_value=85, actual_value=data['demand_el'], fixed=True) }) demand_th = Sink(label='demand_therm', inputs={ bth: Flow(nominal_value=40, actual_value=data['demand_th'], fixed=True) }) # 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='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 results = data['sequences'].sum(axis=0).to_dict() test_results = { (('wind', 'b_el'), 'flow'): 1773, (('pv', 'b_el'), 'flow'): 605, (('b_el', 'demand_elec'), 'flow'): 7440, (('b_el', 'excess_el'), 'flow'): 139, (('pp_chp', 'b_el'), 'flow'): 666, (('pp_lig', 'b_el'), 'flow'): 1210, (('pp_gas', 'b_el'), 'flow'): 1519, (('pp_coal', 'b_el'), 'flow'): 1925, (('pp_oil', 'b_el'), 'flow'): 0, (('b_el', 'heat_pump'), 'flow'): 118, } for key in test_results.keys(): eq_(int(round(results[key])), int(round(test_results[key])))
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])))
import oemof.outputlib as outputlib import oemof.solph as solph import numpy as np import matplotlib.pyplot as plt solver = 'cbc' # set timeindex and create data periods = 20 datetimeindex = pd.date_range('1/1/2019', periods=periods, freq='H') step = 5 demand = np.arange(0, step * periods, step) # set up EnergySystem energysystem = EnergySystem(timeindex=datetimeindex) b_gas = Bus(label='gas', balanced=False) b_el = Bus(label='electricity') energysystem.add(b_gas, b_el) energysystem.add( Sink(label='demand', inputs={b_el: Flow(nominal_value=1, actual_value=demand, fixed=True)})) conv_func = lambda x: 0.01 * x**2 in_breakpoints = np.arange(0, 110, 25) pwltf = solph.custom.PiecewiseLinearTransformer( label='pwltf', inputs={b_gas: solph.Flow(nominal_value=100, variable_costs=1)}, outputs={b_el: solph.Flow()}, in_breakpoints=in_breakpoints,
def create_optimization_model(mode, feedin, initial_batt_cap, cost, cap_pv, cap_batt, iterstatus=None, PV_source=True, storage_source=True, logger=False): if logger == 1: logger.define_logging() ##################################### Initialize the energy system################################################## # times = pd.DatetimeIndex(start='04/01/2017', periods=10, freq='H') times = feedin.index energysystem = EnergySystem(timeindex=times) # switch on automatic registration of entities of EnergySystem-object=energysystem Node.registry = energysystem # add components b_el = Bus(label='electricity') b_dc = Bus(label='electricity_dc') b_oil = Bus(label='diesel_source') demand_feedin = feedin['demand_el'] Sink(label='demand', inputs={ b_el: Flow(actual_value=demand_feedin, nominal_value=1, fixed=True) }) Sink(label='excess', inputs={b_el: Flow()}) Source(label='diesel', outputs={b_oil: Flow()}) generator1 = custom.DieselGenerator( label='pp_oil_1', fuel_input={b_oil: Flow(variable_costs=cost['pp_oil_1']['var'])}, electrical_output={ b_el: Flow(nominal_value=186, min=0.3, max=1, nonconvex=NonConvex(om_costs=cost['pp_oil_1']['o&m']), fixed_costs=cost['pp_oil_1']['fix']) }, fuel_curve={ '1': 42, '0.75': 33, '0.5': 22, '0.25': 16 }) generator2 = custom.DieselGenerator( label='pp_oil_2', fuel_input={b_oil: Flow(variable_costs=cost['pp_oil_2']['var'])}, electrical_output={ b_el: Flow(nominal_value=186, min=0.3, max=1, nonconvex=NonConvex(om_costs=cost['pp_oil_2']['o&m']), fixed_costs=cost['pp_oil_2']['fix'], variable_costs=0) }, fuel_curve={ '1': 42, '0.75': 33, '0.5': 22, '0.25': 16 }) generator3 = custom.DieselGenerator( label='pp_oil_3', fuel_input={b_oil: Flow(variable_costs=cost['pp_oil_3']['var'])}, electrical_output={ b_el: Flow(nominal_value=320, min=0.3, max=1, nonconvex=NonConvex(om_costs=cost['pp_oil_3']['o&m']), fixed_costs=cost['pp_oil_3']['fix'], variable_costs=0) }, fuel_curve={ '1': 73, '0.75': 57, '0.5': 38, '0.25': 27 }) # List all generators in a list called gen_set gen_set = [generator1, generator2, generator3] if PV_source == 1: PV = Source(label='PV', outputs={ b_dc: Flow(nominal_value=cap_pv, fixed_costs=cost['pv']['fix'] + cost['pv']['epc'], actual_value=feedin['PV'], fixed=True) }) else: PV = None if storage_source == 1: storage = components.GenericStorage( label='storage', inputs={b_dc: Flow()}, outputs={ b_dc: Flow(variable_costs=cost['storage']['var'], fixed_costs=cost['storage']['fix']) }, nominal_capacity=cap_batt, fixed_costs=cost['storage']['epc'], capacity_loss=0.00, initial_capacity=initial_batt_cap, nominal_input_capacity_ratio=0.546, nominal_output_capacity_ratio=0.546, inflow_conversion_factor=0.92, outflow_conversion_factor=0.92, capacity_min=0.5, capacity_max=1, initial_iteration=iterstatus) else: storage = None if storage_source == 1 or PV_source == 1: inverter1 = add_inverter(b_dc, b_el, 'Inv_pv') ################################# optimization ############################ # create Optimization model based on energy_system logging.info("Create optimization problem") m = Model(energysystem) ################################# constraints ############################ sr_requirement = 0.2 sr_limit = demand_feedin * sr_requirement rm_requirement = 0.4 rm_limit = demand_feedin * rm_requirement constraints.spinning_reserve_constraint(m, sr_limit, groups=gen_set, storage=storage) # constraints.n1_constraint(m, demand_feedin, groups=gen_set) constraints.gen_order_constraint(m, groups=gen_set) constraints.rotating_mass_constraint(m, rm_limit, groups=gen_set, storage=storage) return [m, gen_set]
def create_energysystem_model(mode, feedin, initial_batt_cap, cost, iterstatus=None, PV_source=True, storage_source=True): """ The function stes up the energy system model and resturns the operational model m, which equals the MILP formulation :param cost: mode optimization mode ['simulation','investment' ] as str feed timeseries holding pv and demand_el values pd.DataFrame initial_batt_cap initial SOC of the battery takes float values from 0-1 cost cost dict derived from get_cost_dict() dict iterstatus None (only important for RH) boolean PV_source include PV source 'True', exclude 'False' boolean storage_source include BSS source 'True', exclude 'False' boolean :return: m operational model oemof.solph.model gen_set list of oemof.solph.custom.EngineGenerator objects integrated in the model """ ##################################### Initialize the energy system################################################## # initialize time steps # times = pd.DatetimeIndex(start='04/01/2017', periods=10, freq='H') times = feedin.index # initialize energy system object energysystem = EnergySystem( timeindex=times ) # switch on automatic registration of entities of EnergySystem-object=energysystem Node.registry = energysystem # add components b_el = Bus( label='electricity' ) b_dc = Bus( label='electricity_dc' ) b_oil = Bus( label='diesel_source' ) demand_feedin = feedin['demand_el'] Sink( label='demand', inputs={b_el: Flow( actual_value=demand_feedin, nominal_value=1, fixed=True )} ) Sink( label='excess', inputs={b_el: Flow()} ) # add source in case of capacity shortages, to still find a feasible solution to the problem # Source(label='shortage_el', # outputs={b_el: Flow(variable_costs=1000)}) Source( label='diesel', outputs={b_oil: Flow()} ) generator1 = custom.EngineGenerator( label='pp_oil_1', fuel_input={b_oil: Flow( variable_costs=cost['pp_oil_1']['var'] )}, electrical_output={b_el: Flow( nominal_value=186, min=0.3, max=1, nonconvex=NonConvex( om_costs=cost['pp_oil_1']['o&m'] ), fixed_costs=cost['pp_oil_1']['fix'] )}, fuel_curve={'1': 42, '0.75': 33, '0.5': 22, '0.25': 16} ) generator2 = custom.EngineGenerator( label='pp_oil_2', fuel_input={b_oil: Flow( variable_costs=cost['pp_oil_2']['var'] )}, electrical_output={b_el: Flow( nominal_value=186, min=0.3, max=1, nonconvex=NonConvex( om_costs=cost['pp_oil_2']['o&m'] ), fixed_costs=cost['pp_oil_2']['fix'], variable_costs=0 )}, fuel_curve={'1': 42, '0.75': 33, '0.5': 22, '0.25': 16} ) generator3 = custom.EngineGenerator( label='pp_oil_3', fuel_input={b_oil: Flow( variable_costs=cost['pp_oil_3']['var'] )}, electrical_output={b_el: Flow( nominal_value=320, min=0.3, max=1, nonconvex=NonConvex( om_costs=cost['pp_oil_3']['o&m'] ), fixed_costs=cost['pp_oil_3']['fix'], variable_costs=0 )}, fuel_curve={'1': 73, '0.75': 57, '0.5': 38, '0.25': 27} ) # List all generators in a list called gen_set gen_set = [generator1, generator2, generator3] sim_params = get_sim_params( cost ) if mode == 'simulation': nominal_cap_pv = sim_params['pv']['nominal_capacity'] inv_pv = None nominal_cap_batt = sim_params['storage']['nominal_capacity'] inv_batt = None elif mode == 'investment': nominal_cap_pv = None inv_pv = sim_params['pv']['investment'] nominal_cap_batt = None inv_batt = sim_params['storage']['investment'] else: raise (UserWarning, 'Energysystem cant be build. Check if mode is spelled correctely. ' 'It can be either [simulation] or [investment]') if PV_source == 1: PV = Source( label='PV', outputs={b_dc: Flow( nominal_value=nominal_cap_pv, fixed_costs=cost['pv']['fix'], actual_value=feedin['PV'], fixed=True, investment=inv_pv )} ) else: PV = None if storage_source == 1: storage = components.GenericStorage( label='storage', inputs={b_dc: Flow()}, outputs={b_dc: Flow( variable_costs=cost['storage']['var'] )}, fixed_costs=cost['storage']['fix'], nominal_capacity=nominal_cap_batt, capacity_loss=0.00, initial_capacity=initial_batt_cap, nominal_input_capacity_ratio=0.546, nominal_output_capacity_ratio=0.546, inflow_conversion_factor=0.92, outflow_conversion_factor=0.92, capacity_min=0.5, capacity_max=1, investment=inv_batt, initial_iteration=iterstatus ) else: storage = None if storage_source == 1 or PV_source == 1: inverter1 = add_inverter( b_dc, b_el, 'Inv_pv' ) ################################# optimization ############################ # create Optimization model based on energy_system logging.info( "Create optimization problem" ) m = Model( energysystem ) ################################# constraints ############################ # add constraints to the model #spinning reserve constraint sr_requirement = 0.2 sr_limit = demand_feedin * sr_requirement #rotating mass constraint rm_requirement = 0.4 rm_limit = demand_feedin * rm_requirement constraints.spinning_reserve_constraint( m, sr_limit, groups=gen_set, storage=storage ) #(N-1) is turned of for Lifuka case study # constraints.n1_constraint(m, demand_feedin, groups=gen_set) #generator order constraint constraints.gen_order_constraint( m, groups=gen_set ) constraints.rotating_mass_constraint( m, rm_limit, groups=gen_set, storage=storage ) return [m, gen_set]
from oemof.solph import EnergySystem, Model, Bus, Sink, Source, Transformer, Flow periods = 20 timeindex = pd.date_range(start='2020-01-01', periods=periods, freq='H') x = np.arange(0, periods, 1) demand_ts = 0.5 * np.cos(x) + 1 pv_ts = 0.5 * np.sin(x) + 0.5 es = EnergySystem(timeindex=timeindex) bus_el = Bus(label='electricity_bus') bus_gas = Bus(label='gas_bus') source_gas = Source(label='gas_source', outputs={bus_gas: Flow(variable_costs=100)}) gas_pp = Transformer(label='powerplant', inputs={bus_gas: Flow()}, outputs={bus_el: Flow(nominal_value=10)}) pv = Source(label='pv', outputs={bus_el: Flow(nominal_value=5, fixed=True, actual_value=pv_ts)})
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])))
# Input Data Reading timeseries = pd.read_excel(datapath, sheet_name="timeseries", index_col=[0], parse_dates=True) timeseries.index.freq = "1H" costs = pd.read_excel(datapath, sheet_name="costs", index_col=[0]) capacity = pd.read_excel(datapath, sheet_name="capacity", index_col=[0]) print("Data and results paths have been created. Input data have been read.") # Energy System Creation es = EnergySystem(timeindex=timeseries.index) setattr(es, "typemap", fc.TYPEMAP) print("The energy system has been created.") # Bus Creation elec_bus_NDE = Bus(label="elec_Bus_NDE") elec_bus_SDE = Bus(label="elec_Bus_SDE") heat_bus_NDE = Bus(label="heat_Bus_NDE") heat_bus_SDE = Bus(label="heat_Bus_SDE") fuel_bus_NDE = Bus(label="fuel_Bus_NDE") fuel_bus_SDE = Bus(label="fuel_Bus_SDE") # Bus Addition to the Energy Sytem es.add(elec_bus_NDE, elec_bus_SDE, heat_bus_NDE, heat_bus_SDE, fuel_bus_NDE, fuel_bus_SDE) # Bus Linking es.add(fc.Link( label='link', carrier='electricity', from_bus=elec_bus_NDE, to_bus=elec_bus_SDE,
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(actual_value=0.5, nominal_value=66.3, fixed=True)}) # demands (electricity/heat) demand_el = Sink( label='demand_elec', inputs={bel: Flow(nominal_value=85, actual_value=0.3, fixed=True)}) demand_th = Sink( label='demand_therm', inputs={bth: Flow(nominal_value=40, actual_value=0.2, fixed=True)}) # 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])))