Seeking Guidance on Modeling EVs in Microgrid

Hello OEMOF community , I am new to energy system modeling and i am working on a hybrid microgrid model using oemof and am looking for the best approach to integrate Electric Vehicles (EVs) as part of the system. I have modeled BEVs using the GenericStorage component to manage charging and discharging functionalities. However, I’m unsure if I should also use Source/Sink components alongside GenericStorage to represent additional functionalities like driving power consumption.

Could anyone share insights or experiences on the best practices for modeling EVs in such scenarios? Should I stick with GenericStorage only, or is there a benefit in also using Source/Sink components?

PS : I have a Binary Data Set (hourly) for my 5 electric vehicles representing the state of each EV
(1 : EV is present in the MG
2 : EV is absent) but i do not know how to use it

here is the snippet code i used for the BEVs :

number_of_evs = 5 
bev_battery_cap = 85  # Kwh

evs_storage = {}

for i in range(number_of_evs):
    ev_label = f'bev_storage_{i+1}'  # here i set a unique label for each EV
    evs_storage[ev_label] = solph.components.GenericStorage(
        label=ev_label,
        inputs={b_electricity: Flow(nominal_value=22)},
        outputs={b_EV: Flow()},
        nominal_storage_capacity=bev_battery_cap,
        loss_rate=0.00001,
        inflow_conversion_factor= 0.90,
        outflow_conversion_factor= 0.80,
        balanced = True,
        #fixed_costs= None, # randomly chosen
        #initial_storage_level = 0 
    )
#adding EVs to the Energysystem
for ev_storage in evs_storage.values():
    Energysystem.add(ev_storage)

Thank you for any advice or guidance!

Hi @Oussama_ZIADI,

Thanks for you interest. At the user meeting in Nordhausen in February this year, Lennart Schürmann gave a talk about this topic. You can find his slides at cloud.oemof.org. I’d consider this approach best practice at this level of detail. (A different approach will be needed for large number of cars.)

Cheers,
Patrik

1 Like

@pschoen

Dear Patrik,

Thank you very much for your guidance. I really appreciate you pointing me to Lennart Schürmann’s talk and the resources at cloud.oemof.org. Following your advice, I’ve developed an energy system model for the integration of EVs within a microgrid, aiming to adhere to best practices at this level of implementation.

I’ve attached a flow chart representation of my current system design. Could you please take a moment to review it and check if the energy system setup is logically sound? I would greatly value your insights and any recommendations you might have.
Looking forward to your expert feedback.

Best regards,
OUSSAMA ZIADI

Hi Oussama,

The energy system graph looks reasonable. You should know that you do not need to add the Link, it’s totally fine to directly connect two Buses. (The original design intended to have a bipartite graph, but this is not enforced and no longer advised. Yo can still have it, though.)

Cheers,
Patrik

PS: From the word ‘Microgrid’ I would have expected something without a grid connection. Technically, there can be connected microgrids, but other people might expect isolated (remote) systems as well.

@pschoen
Dear Patrik,

First and foremost, I would like to extend my deepest gratitude for your previous guidance and the valuable resources you shared .I wanted to clarify indeed that the microgrid I am working on is grid-connected, as you rightly pointed out.Your advice has been instrumental in advancing my project.

I have further developed the energy system model and am now focusing on refining the control strategies for both the stationary electric storage and the EVs. Attached, you will find the flow chart of the proposed control setup along with the code I’ve used for implementation. I am particularly keen to ensure that my approach not only aligns with best practices but is also technically sound.

Could you please take a moment to review these materials and share your thoughts? Your insights would be incredibly helpful, especially in verifying the logic of my control strategy and the efficacy of the associated code.

Thank you once again for your time and support. I look forward to your expert feedback.

Best regards,

Oussama Ziadi

the snippet code i used to implement that :


#Since there is no direct way to implement control strategies for the GenericStorage in OEMOF 0.5.0, it’s possible to imprint the strategies into costs to control the charge/discharge behavior of the Battery storage in order to peak-shave the demand

SOC_min = 0.2
SOC_max = 0.9
Ccharge = np.array([])
Cdischarge = np.array([])
price_treshold =  0.645833 #MAD

for i in range(0, len(data['Demand'][0:len(data['Demand'])])):

    if (data['SOC'].iloc[i] <= SOC_max) and (data['SOC'].iloc[i] > SOC_min) :   
        if data['Demand'].iloc[i]-data['SolarGen'].iloc[i] > 0 :
            if  data['electricity_prices'].iloc[i] > price_treshold  :
                Cost_to_discharge = 0
                Cost_to_charge = 1000
            else :  
                Cost_to_discharge = 1000
                Cost_to_charge = 0      
        else :
            Cost_to_charge = 0
            Cost_to_discharge = 1000

    elif data['SOC'].iloc[i] < SOC_min :
        if data['Demand'].iloc[i]-data['SolarGen'].iloc[i] > 0 :
            if  data['electricity_prices'].iloc[i] < price_treshold  :
                Cost_to_charge = 0
                Cost_to_discharge = 1000
            else :
                Cost_to_charge = 0
                Cost_to_discharge = 0
        else : 
            Cost_to_charge = 0 
    else :
        Cost_to_discharge = 0
        Cost_to_charge = 1000  
        
    Cdischarge = np.append(Cdischarge, Cost_to_discharge)
    Ccharge = np.append(Ccharge, Cost_to_charge)

#creating the Static Storage system as an investment object

capex_bat = float(input('enter capital expenditure : ') )
lifetime_bat = float(input('enter lifetime duration : '))
wacc_bat = float(input('enter weighted average of capital cost : '))

epc_bat = economics.annuity(capex_bat, lifetime_bat, wacc_bat)

static_storage = solph.components.GenericStorage(label = 'Static Storage',
                                                 inputs={b_electricity_dc: solph.Flow(variable_costs=Ccharge)},
        outputs={b_electricity_dc: solph.Flow(variable_costs=Cdischarge)},
        loss_rate=0.00001,
        invest_relation_input_capacity= 1,  # represents C-Rate (charge and discharge rate) , I set it up to 1 , which is the average for lithium-ion batteries in the literature
        invest_relation_output_capacity= 1, #......
        inflow_conversion_factor=0.9, 
        outflow_conversion_factor=0.8,
        #fixed_costs=None,
        balanced=True ,
        investment=Investment(ep_costs=epc_bat),
        #initial_storage_level = 0 
                                                 )

Control strategies can be implemented in the displayed way. However, I’d only do that if you are trying to reproduce the optimal strategy of an optimisation run using exactly the same model. If you do not want optimisation, solph might not be the best tool to use.

To have an optimised strategy for peak shaving, you can follow several approaches. In my opinion, the easiest is to add multiple grid sources, all with a limited nominal_value and with different variable_costs. This way, the optimiser will try to limit the grid load to the cheaper of the grid sources, trying to be below the step to a more expensive one.

@pschoen
Dear Patrik,

Thank you for your detailed response .

I’d like to confirm that I am indeed focusing on optimization within my project. The goal is to configure both the PV capacity and the battery storage optimally. I am using the results(SOC data) of the same model to replicate the control strategy, as you mentioned.

Given this setup, I believe using solph as a tool is appropriate for my needs. I appreciate your insight into using multiple grid sources for peak shaving but i am constrained to use only one grid source with electricity prices as a feedin timeseries to variable_costs .

Dear @Oussama_ZIADI,

if the optimiser is expected to do peak shaving, it has to come with lower costs. You might need to manually calculate different economic costs if high peaks do not come with associated economical costs but are avoided for another reason. If you want to minimise the highest peak (and the next one once it becomes the highest, and so forth), an investment into the nominal_value of the grid connection flow would be the direct way to do it.

1 Like

@pschoen
thank you very much for your time and the valuable informations

I have another question related to that topic: Does Oemof offer the flexibility to implement flow charts for dispatch operations? If so, could you provide some examples?
BR,
Oussama ziadi

Honestly, I don’t feel like solph really is the tool you want to use. What you present here looks like you want to manually implement control based on decision trees. However, solph is a linear optimiser, meaning that the found control typically cannot be expressed in terms of a control strategy with a closed formulation.

We once implemented an approach that first optimises and then tries to find strategies that come as close to the optimal operation as possible. You can find a description in [1]. It implements linear discriminant analysis instead of decision trees, but the latter could be parametrised the same way.

1: Energies | Free Full-Text | Deduction of Optimal Control Strategies for a Sector-Coupled District Energy System