Giter VIP home page Giter VIP logo

Comments (16)

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024 1

This would be specified as below:

import energypylinear as epl

#  2.0 MW, 4.0 MWh battery
asset = epl.battery.Battery(power_mw=2, capacity_mwh=4, efficiency=0.9)

results = asset.optimize(
  electricity_prices=[100.0, 50, 200, -100, 0, 200, 100, -100],
  freq_mins=60,
  initial_charge_mwh=1,
  final_charge_mwh=3,
  cycle_cost=1.0
)

This would assign a cost of $1 when moving 4 MWh of energy (either as charge or discharge).

In the objective function, we would need to add something like:

cost = cycle_cost * absolute_battery_charge_mwh / capacity_mwh

What do you think @rzylius ?

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024 1

I'm happy to add a cost per cycle - where a cycle is defined as discharging by the full battery capacity, as per https://en.wikipedia.org/wiki/Charge_cycle

The model will be penalized to discharge. The user will input a $/cycle number, where 1 cycle = battery capacity in kWh.

Would you like to do the implementation @rzylius?

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

Hi @rzylius

Yes I can add this - it will be a cost that is applied to every MWh of energy used for charging or discharging (gross of losses).

from energy-py-linear.

rzylius avatar rzylius commented on June 3, 2024

Hi Adam,

could you elaborate on this approach? Where one shoud add the cost of battery cycle?

from energy-py-linear.

rzylius avatar rzylius commented on June 3, 2024

Dear @ADGEfficiency ,

Maybe it would be more practical to input the cost of the cycle per Mwh (so we would input $.25 per mhw, rather than $1 per 4Mhw? This is probably the most used parameter. Then the cost function would be:

cost = cycle_cost * absolute_battery_charge_mwh

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

Dear @ADGEfficiency ,

Maybe it would be more practical to input the cost of the cycle per Mwh (so we would input $.25 per mhw, rather than $1 per 4Mhw? This is probably the most used parameter. Then the cost function would be:

cost = cycle_cost * absolute_battery_charge_mwh

Do you have any reference for the cost per cycle per MWh - any examples of it being used that way?

from energy-py-linear.

rzylius avatar rzylius commented on June 3, 2024

Random article on the subject:

https://www.spiritenergy.co.uk/kb-battery-storage-for-solar-residential-economics

"The lifetime cost of small scale battery storage is now around 13p per kWh. This is the cost ‘per cycle’ of charging and discharging 1 kWh (excluding the cost of the electricity used to charge the battery)."

I understand metric is officially called "Levelized Cost of Energy Storage (LCOES)".
https://www.nature.com/articles/s41467-019-09988-z

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

I'm not really sure I agree that charging and discharging 1 MWh is one cycle - usually 1 cycle is charge + discharge of entire battery.

I also don't think this is at all related to LCOES - that is a metric to recover the total cost of a project.

What you want is to create an opportunity cost for charging - this opportunity cost is the long term maintenance cost you incurr for putting the battery through one more cycle.

What do you think @rzylius ?

from energy-py-linear.

rzylius avatar rzylius commented on June 3, 2024

Totally agree with you.

Probably the real discussion how this applies to the non-full-cycle charging-discharging.

My thinking was, that battery wear applies to increamental charge/discharge the same way as it does with full cycles. There are a lot of articles with reference to research on "how to propolng battery life". They state, that shallow discharge prolongs lifespan of batteries, but it is clear, that shallow discharge wears down battery as well.

Because of that my thinking was, that the metric of 1kwh of charge/discharge is logical - every kwh put and withdrawn wears down the battery. Actual cost varies depending of DOD, SOC, charge/discharge current, but I thought introducing variable cost would be overkill.

In home based scenarios homeowners probably has variety of scenarios.

So in many home I guess there will be no intention of doing full-cycles, as in many countries we do not sell electricity. We buy it at low market price of the hour and "do not use" it when the electricity is expensive. That is discharge part is not discharging at maximum, but rather satisfy all house needs for that hour. Which is my case well.

In this scenario one would expect algorithm to use opportunities to charge / discharge without reaching 100% SOC and not going down to bottom of DOD, and iddling when LCOES is too high in comparison difference of electricity prices. Thus having a battery of 20kwh, charging 5kwh and discharging 8kwh should be quite usual (rather than full charge / full discharge cycle).

With such scenario, I thought cost per 1kwh is reasonable. Does this makes sense?

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

In this scenario one would expect algorithm to use opportunities to charge / discharge without reaching 100% SOC and not going down to bottom of DOD, and iddling when LCOES is too high in comparison difference of electricity prices. Thus having a battery of 20kwh, charging 5kwh and discharging 8kwh should be quite usual (rather than full charge / full discharge cycle).

I don't think LCOES is relevant at all here. LCOES includes capital cost - capital costs are not relevant at all to dispatching a battery for wholesale dispatch. They are relevant at the feasibility stage, but not at the dispatch/operation stage. I'm concerned you are misunderstanding the problem if you think LCOES is relevant here.

They state, that shallow discharge prolongs lifespan of batteries, but it is clear, that shallow discharge wears down battery as well.

These two things directly contradict each other. You say shallow discharge prolongs lifespan but also wears down the battery.

With such scenario, I thought cost per 1kwh is reasonable.

I'm still not 100% sure what to think - the unitization of the cost per MWh is good. I think it's fine.

from energy-py-linear.

rzylius avatar rzylius commented on June 3, 2024

Sorry for messy thinking process. Please keep in mind, that I am trying to think how battery is used in home installation, rather than wholesale scenario.

LCOES to my inderstanding is relevan in the sense, that one should not do charge/discharge when the price difference is too small. This is a reference point for evaluating.

Shallow discharge wears battery less than deep discharge, this was my point. As I stated, I thought attributing variant cost would add too much complexity, so I suggested that shallow/deep should be disregarded and we stay with fixed cost. But at the same time shallow charge/discharge wear means, that every 1 kwh of charge discharge wears the battery (not only full cycles). So my logic says that having cost per kwh rather per cycle is closer to real world.

Anyways, @ADGEfficiency , thanks a lot for your work and discussion.

from energy-py-linear.

rzylius avatar rzylius commented on June 3, 2024

@ADGEfficiency , thanks for your efforts!

I will implement to use it to my scenarios and report back.

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

@ADGEfficiency , thanks for your efforts!

I will implement to use it to my scenarios and report back.

@rzylius - do you still need this feature?

from energy-py-linear.

Minvyd avatar Minvyd commented on June 3, 2024

@ADGEfficiency , thanks for your efforts!
I will implement to use it to my scenarios and report back.

@rzylius - do you still need this feature?

I think this feature would be helpful, if you want to compensate the cost of charging and the battery degradation you need to set a threshold which the function would deem useful. And I think the battery degradation could be written as a linear function (half the cycle capacity, half the cycle cost). Where Battery_initial_investment/warranty_cycles = One_cycle_cost (Charging and discharging) would give us a metric to watch how much we should make when performing the charging/discharging events. As an example if the battery has a capacity of 4 MWh and a full cycle costs 100 USD then when we perform charging/discharging event if (assuming our battery c rate is equal to 1) the battery would make > 100 USD. Then those hours would be chosen by the algorithm to maximize profit.

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

@ADGEfficiency , thanks for your efforts!
I will implement to use it to my scenarios and report back.

@rzylius - do you still need this feature?

I think this feature would be helpful, if you want to compensate the cost of charging and the battery degradation you need to set a threshold which the function would deem useful.

I'd suggest we can stick too what we discussed above:

The model will be penalized to discharge. The user will input a $/cycle number, where 1 cycle = battery capacity in kWh.

@Minvyd are you interested in implementing this change? I'm quite keen to get others contributing so I can start to iron out the internal things that are hard to work with / understand.

from energy-py-linear.

ADGEfficiency avatar ADGEfficiency commented on June 3, 2024

@rzylius @Minvyd

The 1.2.0 release includes the ability to model a battery cycle cost as a custom objective function:

import numpy as np
import energypylinear as epl

assets = [
    epl.Battery(power_mw=20, capacity_mwh=20)
]
site = epl.Site(
    assets=assets,
    electricity_prices=np.random.normal(0, 1000, 48)
)
terms=[
    {
        "asset_type":"site",
        "variable":"import_power_mwh",
        "interval_data":"electricity_prices"
    },
    {
        "asset_type":"site",
        "variable":"export_power_mwh",
        "interval_data":"electricity_prices",
        "coefficient":-1
    },
    {
        "asset_type": "battery",
        "variable": "electric_discharge_mwh",
        "interval_data": "electricity_prices",
        "coefficient": 0.25
    }
]
site.optimize(objective={"terms": terms})

Please take a look and see if this solves your use cases. If I don't hear from you within a few weeks I'll close the issue as complete.

You can find more detail about custom objective functions in the documentation.

from energy-py-linear.

Related Issues (17)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.