def test_generic_storage_with_old_parameters(): deprecated = { 'nominal_capacity': 45, 'initial_capacity': 0, 'capacity_loss': 0, 'capacity_min': 0, 'capacity_max': 0, } # Make sure an `AttributeError` is raised if we supply all deprecated # parameters. with pytest.raises(AttributeError) as caught: components.GenericStorage( label='`GenericStorage` with all deprecated parameters', **deprecated) for parameter in deprecated: # Make sure every parameter used is mentioned in the exception's # message. assert parameter in str(caught.value) # Make sure an `AttributeError` is raised for each deprecated # parameter. pytest.raises( AttributeError, components.GenericStorage, **{ "label": "`GenericStorage` with `{}`".format(parameter), parameter: deprecated[parameter], })
def test_generic_storage_with_convex_invest_offset(): """Offset value is given and nonconvex is False.""" with pytest.raises(AttributeError, match=r"If `nonconvex` is `False`, the `offset`"): bel = Bus() components.GenericStorage(label='storage6', inputs={bel: Flow()}, outputs={bel: Flow()}, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, investment=Investment(offset=10))
def test_generic_storage_with_non_convex_invest_maximum(): """No investment maximum at nonconvex investment.""" with pytest.raises(AttributeError, match=r"Please provide an maximum investment value"): bel = Bus() components.GenericStorage(label='storage6', inputs={bel: Flow()}, outputs={bel: Flow()}, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, investment=Investment(nonconvex=True))
def test_generic_storage_3(): """Nominal value defined with investment model.""" bel = Bus() components.GenericStorage( label='storage4', nominal_storage_capacity=45, inputs={bel: Flow(nominal_value=23, variable_costs=10e10)}, outputs={bel: Flow(nominal_value=7.5, variable_costs=10e10)}, loss_rate=0.00, initial_storage_level=0, inflow_conversion_factor=1, outflow_conversion_factor=0.8)
def test_generic_storage_with_non_convex_investment(): """Tests error if `offset` and `existing` attribute are given.""" with pytest.raises(AttributeError, match=r"Values for 'offset' and 'existing' are given"): bel = Bus() components.GenericStorage(label='storage4', inputs={bel: Flow()}, outputs={bel: Flow()}, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, investment=Investment(nonconvex=True, existing=5, maximum=25))
def test_generic_storage_2(): """Nominal value defined with investment model.""" bel = Bus() with pytest.raises(AttributeError, match="If an investment object"): components.GenericStorage(label='storage3', nominal_storage_capacity=45, inputs={bel: Flow(variable_costs=10e10)}, outputs={bel: 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=23))
def test_generic_storage_1(): """Duplicate definition inflow.""" bel = Bus() with pytest.raises(AttributeError, match="Overdetermined."): components.GenericStorage(label='storage1', inputs={bel: Flow(variable_costs=10e10)}, outputs={bel: Flow(variable_costs=10e10)}, loss_rate=0.00, initial_storage_level=0, invest_relation_input_output=1, invest_relation_output_capacity=1, invest_relation_input_capacity=1, investment=Investment(), inflow_conversion_factor=1, outflow_conversion_factor=0.8)
def test_generic_storage_with_invest_and_fixed_losses_absolute(): """ Storage with fixed losses in the investment mode but no minimum or existing value is set an AttributeError is raised because this may result in storage with zero capacity but fixed losses. """ msg = (r"With fixed_losses_absolute > 0, either investment.existing or" " investment.minimum has to be non-zero.") with pytest.raises(AttributeError, match=msg): bel = Bus() components.GenericStorage( label='storage4', inputs={bel: Flow()}, outputs={bel: Flow()}, investment=Investment(ep_costs=23, minimum=0, existing=0), fixed_losses_absolute=[0, 0, 4], )
}) Sink(label='demand_el', inputs={ bel: Flow(actual_value=timeseries['demand_el'], fixed=True, nominal_value=500) }) components.GenericStorage( label='storage', inputs={bel: Flow()}, outputs={bel: Flow()}, capacity_loss=0.00, initial_capacity=0.5, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, inflow_conversion_factor=0.95, outflow_conversion_factor=0.95, investment=Investment(ep_costs=costs['storage']['epc'])) ################################################################# # Create model and solve ################################################################# m = Model(energysystem) # om.write(filename, io_options={'symbolic_solver_labels': True}) m.solve(solver='cbc', solve_kwargs={'tee': True})
def diesel_only(mode, feedin, initial_batt_cap, cost, 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] 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 ############################ 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]
Sink(label='demand_th', inputs={ bth: Flow(actual_value=timeseries['demand_th'], fixed=True, nominal_value=500) }) Sink(label='spot_el', inputs={bel: Flow(variable_costs=timeseries['price_el'])}) components.GenericStorage(label='storage_th', inputs={bth: Flow()}, outputs={bth: Flow()}, nominal_capacity=1500, capacity_loss=0.00, initial_capacity=0.5, nominal_input_capacity_ratio=1 / 6, nominal_output_capacity_ratio=1 / 6) ########################################################################## # Create model and solve ########################################################################## m = Model(energysystem) # om.write(filename, io_options={'symbolic_solver_labels': True}) m.solve(solver='cbc', solve_kwargs={'tee': True}) results = processing.results(m)
outputs={ bel: Flow(nominal_value=50, nonconvex=NonConvex(), variable_costs=60, negative_gradient={'ub': 0.05, 'costs': 0}, positive_gradient={'ub': 0.05, 'costs': 0})}) Source(label='pp_bio', outputs={ bel: Flow(nominal_value=5, variable_costs=100)}) components.GenericStorage( label='storage_el', inputs={ bel: Flow()}, outputs={ bel: Flow()}, nominal_capacity=40, nominal_input_capacity_ratio=1/10, nominal_output_capacity_ratio=1/10, ) # heat componentes bth = Bus(label='bth') bgas = Bus(label='bgas') Source(label='gas', outputs={ bgas: Flow()})
}) Sink(label='demand_th', inputs={ bth: Flow(actual_value=timeseries['demand_th'], fixed=True, nominal_value=500) }) Sink(label='spot_el', inputs={bel: Flow(variable_costs=timeseries['price_el'])}) components.GenericStorage(label='storage_th', inputs={bth: Flow(nominal_value=1500 / 6)}, outputs={bth: Flow(nominal_value=1500 / 6)}, nominal_capacity=1500, capacity_loss=0.00, initial_capacity=0.5) ########################################################################## # Create model and solve ########################################################################## m = Model(energysystem) # om.write(filename, io_options={'symbolic_solver_labels': True}) m.solve(solver='cbc', solve_kwargs={'tee': True}) results = processing.results(m) views.node(results, 'bth')['sequences'][1:168].plot(drawstyle='steps')
def test_connect_invest(): date_time_index = pd.date_range('1/1/2012', periods=24 * 7, freq='H') energysystem = EnergySystem(timeindex=date_time_index) network.Node.registry = energysystem # Read data file full_filename = os.path.join(os.path.dirname(__file__), 'connect_invest.csv') data = pd.read_csv(full_filename, sep=",") logging.info('Create oemof objects') # create electricity bus bel1 = Bus(label="electricity1") bel2 = Bus(label="electricity2") # create excess component for the electricity bus to allow overproduction Sink(label='excess_bel', inputs={bel2: Flow()}) Source(label='shortage', outputs={bel2: Flow(variable_costs=50000)}) # create fixed source object representing wind power plants Source(label='wind', outputs={bel1: Flow(fix=data['wind'], nominal_value=1000000)}) # create simple sink object representing the electrical demand Sink(label='demand', inputs={bel1: Flow(fix=data['demand_el'], nominal_value=1)}) storage = components.GenericStorage( label='storage', inputs={bel1: Flow(variable_costs=10e10)}, outputs={bel1: Flow(variable_costs=10e10)}, loss_rate=0.00, initial_storage_level=0, invest_relation_input_capacity=1 / 6, invest_relation_output_capacity=1 / 6, inflow_conversion_factor=1, outflow_conversion_factor=0.8, investment=Investment(ep_costs=0.2), ) line12 = Transformer( label="line12", inputs={bel1: Flow()}, outputs={bel2: Flow(investment=Investment(ep_costs=20))}) line21 = Transformer( label="line21", inputs={bel2: Flow()}, outputs={bel1: Flow(investment=Investment(ep_costs=20))}) om = Model(energysystem) constraints.equate_variables(om, om.InvestmentFlow.invest[line12, bel2], om.InvestmentFlow.invest[line21, bel1], 2) constraints.equate_variables( om, om.InvestmentFlow.invest[line12, bel2], om.GenericInvestmentStorageBlock.invest[storage]) # if tee_switch is true solver messages will be displayed logging.info('Solve the optimization problem') om.solve(solver='cbc') # check if the new result object is working for custom components results = processing.results(om) my_results = dict() my_results['line12'] = float(views.node(results, 'line12')['scalars']) my_results['line21'] = float(views.node(results, 'line21')['scalars']) stor_res = views.node(results, 'storage')['scalars'] my_results['storage_in'] = stor_res[(('electricity1', 'storage'), 'invest')] my_results['storage'] = stor_res[(('storage', 'None'), 'invest')] my_results['storage_out'] = stor_res[(('storage', 'electricity1'), 'invest')] connect_invest_dict = { 'line12': 814705, 'line21': 1629410, 'storage': 814705, 'storage_in': 135784, 'storage_out': 135784 } for key in connect_invest_dict.keys(): eq_(int(round(my_results[key])), int(round(connect_invest_dict[key])))
def 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]