Charge battery based on flexible energy tariffs

Dear reader,

I am trying to optimize a simple model with oemof-solph, using flexible energy tariffs. I have implemented the most basic situation I could think of where the energy prices follow a sinusoidal trend, there is a battery that charges when energy is cheap and feeds back in to the grid when energy is expensive, while meeting demand.

The battery however does not charge.

I have created energy systems where the battery charges, but I could not get it to work with flexible tariffs. I am lost. Does anybody understand what I am doing wrong?

See example code below (and note vertical scroll bar):

    import os
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    from oemof.solph import Sink, Source, Transformer, Bus, Flow, Model, EnergySystem, processing,     views, GenericStorage
    from oemof_visio import ESGraphRenderer

    ### initialize and provide data

    datetimeindex = pd.date_range('1/1/2016', periods=24*10, freq='H')
    filename = 'oemof/input_data.csv'
    filename = os.path.join(os.getcwd(), filename)
    data = pd.read_csv(filename, sep=",")
    def negative(positive_list):
        return [-elem for elem in positive_list]
    energy_prices = 0.50 + np.sin(2 * np.pi / 24 * np.linspace(0, len(datetimeindex), len(datetimeindex)))/2
    energy_prices = energy_prices.tolist()
    energysystem = EnergySystem(timeindex=datetimeindex)

    ### electricity

    electricityBus = Bus(label='electricityBus')
    energysystem.add(electricityBus)

    ### grid

    energysystem.add(Source(label='grid', outputs={electricityBus: Flow(variable_cost=energy_prices)}))

    ### feed in, variable cost set to negative energy prices to get the full price of electricity as feed in tariff

    energysystem.add(Sink(label='excessElectricity', inputs={electricityBus: Flow(nominal_value=10, variable_cost=negative(energy_prices))}))

### battery

    energysystem.add(GenericStorage(
        label='battery',
        inputs={electricityBus: Flow(nominal_value=200, variable_cost=0)},
        outputs={electricityBus: Flow(nominal_value=10, variable_cost=0)},
        nominal_storage_capacity=1000,
        initial_storage_level=0.1,
        balanced=False,
    ))

### demands (electricity)

    energysystem.add(Sink(label='demandElectricity', inputs={electricityBus: Flow(nominal_value=85, fix=data['demandElectricity'])}))
    graph_renderer = ESGraphRenderer(energysystem)
    graph_renderer.view()
    pd.options.plotting.backend = "plotly"
    def transform_multi_col_name(col_names):
        return [f'{col_name[0][0]} {col_name[0][1]}' for col_name in col_names]
    def plotAll(data, ylabel='value', solver='GLPK'):
        data.columns = transform_multi_col_name(data.columns)
        data["EnergyPricesTimes100"] = np.asarray(energy_prices)*100
        for k, v in energysystem.results[solver].items():
            data["Storage"] = v['sequences']
            break
    fig = data.plot()
    fig.update_layout(yaxis_title=ylabel)
    fig.show()

### create a glpk optimization model based on energy_system

    glpkModel = Model(energysystem=energysystem)
    glpkModel.solve(solver='glpk', solve_kwargs={'tee': True, 'keepfiles': False})
    energysystem.results['GLPK'] = processing.results(glpkModel)
    energysystem.results['GLPKmeta'] = processing.meta_results(glpkModel)
    glpkElectricityResults = views.node(energysystem.results['GLPK'], 'electricityBus')
    glpkDataElectricity = glpkElectricityResults['sequences']
    plotAll(glpkDataElectricity, ylabel='Watt', solver='GLPK')

input data


    ### The input data looks as follows:

    demandThermal,demandElectricity,solar,wind
    0.1469452338,0.6137606201,0.00E+000,2.78E-001
    0.1500444621,0.6137606201,0.00E+000,2.81E-001
    0.1569258683,0.5575605123,0.00E+000,2.83E-001
    0.1740503842,0.5317384943,0.00E+000,2.83E-001
    0.2175136794,0.5198798737,0.00E+000,2.52E-001
    0.2993166845,0.4987936035,0.00E+000,1.86E-001
    0.3541620446,0.4596755564,0.00E+000,1.86E-001
    0.3316082816,0.456313047,0.00E+000,1.85E-001
    0.3062301219,0.4653995226,9.10E-003,1.85E-001

etc…

Thanks in advance!

Hi @Maurice and welcome to the board,

The problem seems to be rather easy and is caused by something I’d now call a design flaw in solph: Currently, the constructors accept any keyword argument. If its unknown, it adds a parameter to the class. However, often this parameter is then silently ignored. (We are about to change that.)

In your case, the flows have variable_cost as you defined it. However, the parameter of the class variable_costs (with an s) defaults to 0. So, there is no benefit in storing anything.

PS: In the early days, this feature helped with rapid prototyping. But we are beyond that now.

1 Like

Hi @pschoen, thank you both for the welcome and the quick reply.

Your solution works!

Looking forward to future development :smiley: