MarcBerliner / PETLION.jl

High-performance simulations of the Porous Electrode Theory for Li-ion batteries
MIT License
65 stars 11 forks source link

Question regarding run time (and memory usage) improvements for high-resolution time simulation. #108

Open androlos opened 12 months ago

androlos commented 12 months ago

As there is no Discussion Tab, I post my question as an Issue (I hope this is ok, as it has been done before). I am currently trying to simulate every second of a charging procedure separately. This comes with an about 360x longer runtime and a lot more memory usage.

Is there currently a way to do this faster and a way to deal with the excessive memory use?

julia> function fc1(p)
           sol = solution()
           p.opts.SOC = 0
           simulate!(sol, p, 3600, I = 1)
       end
fc1 (generic function with 1 method)

julia> function fc2(p)
           sol = solution()
           p.opts.SOC = 0
           for i in 1:3600
               simulate!(sol, p, 1, I = 1)
           end
       end
fc2 (generic function with 1 method)

julia> @time fc1(p)
  0.026543 seconds (2.93 k allocations: 993.337 KiB, 37.08% compilation time)
PETLION simulation
 --------
 Run:     I
 Time:    1.0 hr
 Current: 1C
 Voltage: 4.1637 V
 Power:   121.7 W/m²
 SOC:     1.0
 Exit:    Final time reached

julia> @time fc2(p)
  9.644558 seconds (1.02 M allocations: 2.907 GiB, 6.50% gc time, 1.05% compilation time)
PETLION simulation
 --------
 Runs:    3600 I
 Time:    1.0 hr
 Current: 1C
 Voltage: 4.1637 V
 Power:   121.7 W/m²
 SOC:     1.0
 Exit:    Final time reached
MarcBerliner commented 12 months ago

To improve the performance, you can pass a function with the time-varying current instead of starting and stopping the simulation.

First, create an interpolation object of your time-series data using the Interpolations.jl package. Write a function wrapping the interpolator, then give PETLION the specific time points where a discontinuity occurs, tdiscon.

t = collect(0:1:3600)
I = ones(length(t))

using Interpolations
itp = linear_interpolation(t, I; extrapolation_bc=Throw())
I_func(t) = itp(t)

@time sol = simulate(p, 3600; I=I_func, tdiscon=t, SOC=0, maxiters = 100_000)
julia> @time sol = simulate(p, 3600; I=I_func, tdiscon=t, SOC=0, maxiters = 100_000)
  0.132629 seconds (58.84 k allocations: 2.241 MiB)

I would not recommend using a piecewise constant input for I, but rather a linear interpolation, spline interpolation, etc.

For more information on variable inputs, see https://github.com/MarcBerliner/PETLION.jl/blob/master/examples/variable_input_functions.ipynb

androlos commented 11 months ago

Thank you very much for your answer and please excuse my late response. I had read the examples before and passing a time-varying function was considered. However my problem has a slightly different nature.

I am trying to develop charging strategies by analysing closed loop systems, where I provide a current for a short timescale and derive voltage and aging related measurements (SOH, c_e, j_s, film, etc.) which influence the current for the next timesteps.

So passing time-varying functions would help me validate the results, but I was wondering if PETLION could also be used as the system model.

klinders commented 3 months ago

Good evening all, I have a similar question as @androlos and I would love to know if there is a solution. I am working on a battery pack model where the degradation is calculated for cells and cell zones within the pack. Because I want to include the cell interactions and the thermal management, I want to step the battery simulation myself. I really love the speed and simplicity of the PETLION package but when I step the simulation through time manually (like suggested by @androlos ) the simulation gets slow.

What would be your suggestion on how to approach this?

Would love to use your package and get involved.