Change the nominal_input_capacity_ratio of a storage

Hello,

i would like to optimize the capacity and the input/output ratio of a storage.

I want to create a loop in which the storage change its input_ratio.
How can i reconfigure a storage after the initialization?


bat=solph.components.GenericStorage(label='Batterie',
                                          inputs={bel: solph.Flow()},
                                          outputs={bel: solph.Flow()},
                                          nominal_input_capacity_ratio=0.2, 
                                          nominal_output_capacity_ratio=0.2,
                                          capacity_loss=0.001,
                                          inflow_conversion_factor=0.95, 
                                          outflow_conversion_factor=0.95,
                                          investment=solph.Investment(ep_costs=epc))
energysystem.add(bat)
for x in range(0, 3):
 bat=energysystem.flows(inputs={bel: solph.Flow()},   ##### HOW TO CHANGE?
                         outputs={bel: solph.Flow()},
                         nominal_input_capacity_ratio=0.2*x, 
                         nominal_output_capacity_ratio=0.2*x,
                         capacity_loss=0.001,
                         inflow_conversion_factor=0.95, 
                         outflow_conversion_factor=0.95,
                         investment=solph.Investment(ep_costs=epc))
    

    # initialise the operational model (create problem)
    om = solph.Model(energysystem)
    om.solve(solver='cbc', solve_kwargs={'tee': True})
    my_results = processing.results(om)
    batcap[x]= outputlib.views.node(my_results, 'None')['scalars'][0]

I do not fully understand your question, but it might be connected to Fabian’s question (I have to admit that his title is not helpful to see the connection).

Instead of using the Investment object you can also loop around the parameters to find the best configuration, but you have to looper over the whole creation of the energy system.

see uwes edit…

1 Like

I edited my posting from above because the solution does not work.

I understand that you may not want to recreate the whole EnergySystem (especially in large systems) if you just want to change one parameter in the storage class. A good way would be to delete the storage and add a new one with the changed attributes. The problem is, that it is not possible to remove an object from the EnergySystem at the moment. I will think about how this could be done in the future.

Until then you have to loop over the whole energy system. The effort is not to big because creating the energy system is very fast compared to building the model or solving the model.

I talked to another developer and it is not that simple to remove a component from an existing energy system but you could create a dictionary beforehand and replace the adapted component within the loop. The following example is based on the basic_example of the oemof examples. I just copied the interesting parts.

nodes = {}
results = {}

my_date_time_index = ...
data = ...

nodes['b_ng'] = solph.Bus(label="natural_gas")
nodes['b_el'] = solph.Bus(label="electricity")
nodes['wind'] = solph.Source(label='wind', outputs={nodes['b_el']: solph.Flow(
    actual_value=data['wind'], nominal_value=1000000, fixed=True)}))

[...]

for x in [0.6, 0.8, 1.0]:
    scenario = 'my_scenario_{0}'.format(str(x))
    nodes['bat'] = solph.components.GenericStorage(
        label='Batterie',
        inputs={nodes['b_el']: solph.Flow()},  
        outputs={nodes['b_el']: solph.Flow()},
        nominal_input_capacity_ratio=0.2*x, 
        nominal_output_capacity_ratio=0.2*x,
        capacity_loss=0.001,
        inflow_conversion_factor=0.95, 
        outflow_conversion_factor=0.95,
        investment=solph.Investment(ep_costs=epc))
    energysystem = solph.EnergySystem(timeindex=my_date_time_index)
    energysystem.add(*nodes.values())
    model = solph.Model(energysystem)
    model.solve(solver='cbc')
    results[scenario] = outputlib.processing.results(model)

# Use pickle to store the results of all scenarios.
pickle.dump(results, open('my_filename.pkl', 'wb'))
1 Like

@Fabian Thanks to you post I re-thought my solution and found a better one.

Thank You for the good suggestion!

But i think the problem is that “investment = solph.Investement(ep_costs=epc))” does not belong to energysystem.flows(…). I have following error:

    investment=solph.Investment(ep_costs=epc))

TypeError: flows() got an unexpected keyword argument 'inputs'
_______________________________________________________
code:


import pandas as pd
from oemof import solph
from oemof.outputlib import processing
import oemof.outputlib as outputlib
import os
nodes = {}
results = {}

nodes['b_el'] = solph.Bus(label="electricity")
try:
    import matplotlib.pyplot as plt
except ImportError:
    plt = None

data_time_index = pd.date_range('1/1/2018', periods=35040, freq='0.25H')
energysystem = solph.EnergySystem(timeindex=data_time_index)

# Daten einlesen
filename = os.path.join(os.path.dirname(__file__), 'maslingstrasse41_wirt.csv')
data = pd.read_csv(filename)

# Elektrischen Bus initialisieren
bel = solph.Bus(label="electricity")
energysystem.add(bel)

# demands (electricity/heat)
energysystem.add(solph.Sink(label='last', inputs={bel: solph.Flow(
        variable_costs=0, nominal_value=1, actual_value=data['last'], fixed=True)}))
    
# Solareinspeisung
energysystem.add(solph.Source(label='pv', outputs={bel: solph.Flow(
        variable_costs=0, actual_value=data['pv'], nominal_value=1, fixed=True)}))
   
# NetzĂĽberschuss, Einspeisung
energysystem.add(solph.Sink(label='Netzeinspeisung', inputs={bel: solph.Flow(
        variable_costs=-0.123)}))

# Knappheitsquelle, Netzbezug
energysystem.add(solph.Source(label='Netzbezug', outputs={bel: solph.Flow(
        variable_costs=0.287)}))

# Invest Definitionen
capex = 300  # investment cost
lifetime = 20  # life expectancy
wacc = 0.059  # weighted average of capital cost
epc = capex * (wacc * (1 + wacc) ** lifetime) / ((1 + wacc) ** lifetime - 1)


for x in [0.6, 0.8, 1.0]:
    scenario = 'my_scenario_{0}'.format(str(x))
    nodes['bat'] = energysystem.flows(
        inputs={nodes['b_el']: solph.Flow()},  
        outputs={nodes['b_el']: solph.Flow()},
        nominal_input_capacity_ratio=0.2*x, 
        nominal_output_capacity_ratio=0.2*x,
        capacity_loss=0.001,
        inflow_conversion_factor=0.95, 
        outflow_conversion_factor=0.95,
        investment=solph.Investment(ep_costs=epc))
    energysystem = solph.EnergySystem(timeindex=data_time_index)
    energysystem.add(*nodes.values())
    model = solph.Model(energysystem)
    model.solve(solver='cbc')
    results[scenario] = outputlib.processing.results(model)

# Use pickle to store the results of all scenarios.
pickle.dump(results, open('my_filename.pkl', 'wb'))

This was a copy/paste error. I copied the wrong storage from your example. It has to be the normal initialisation of the storage. I edited the post above to avoid confusion.

Does it work now? If it does you could mark this topic as solved.

I modified the code. There is now a loop, which repeat most of the code.
Thank You for the help!

I can’t mark it, I did not found where to do it…

It should be a possibility to mark one answer as solution but this can only be done by you.

I am only able to: like, share, flag, bookmark, reply…

Okay, now I understand. You first have to change the category from “Modelling” to “Q&A”, then you can mark the issue as solved. Modelling is a discussion category while Q&A is for concrete questions/problems.