Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import new OCP curves from test data #3407

Closed
yuchengluo1 opened this issue Oct 4, 2023 · 7 comments
Closed

Import new OCP curves from test data #3407

yuchengluo1 opened this issue Oct 4, 2023 · 7 comments

Comments

@yuchengluo1
Copy link

Hi, I am introducing ocp curve data for my own batteries with reference to the method in #600, which is:

model = pybamm.lithium_ion.DFN()
param = pybamm.ParameterValues("Chen2020")
data_cathode = pd.read_excel(...)
interpolated_OCP_cathode = interpolate.CubicSpline(
data_cathode.to_numpy()[:, 0],
data_cathode.to_numpy()[:, 1],
extrapolate=True
)
dOCP_cathode = interpolated_OCP_cathode.derivative()

@primitive
def OCP_cathode(sto):
print("Input to OCP_cathode:", sto)
out = interpolated_OCP_cathode(sto)[0]
if np.size(out) == 1:
out = np.array([out])
return out

def OCP_cathode_vjp(ans,sto):
sto_shape = sto.shape
return lambda g: np.full(sto_shape, g) * dOCP_cathode(sto)

defvjp(OCP_cathode, OCP_cathode_vjp)

param.update({
"Positive electrode OCP [V]": OCP_cathode,
})

Unfortunately, a problem has arisen when I try to run the simulation (for example, sim.solve([0,24])). The error is: TypeError: float() argument must be a string or a real number, not 'Scalar'.

The format of imported data looks fine for me:
print(data_cathode)
SOC-dch U-dch
50 0.00 3.52
49 0.02 3.61
48 0.04 3.62
47 0.06 3.63
46 0.08 3.64
45 0.10 3.65
...
5 0.90 4.03
4 0.92 4.1
3 0.94 4.11
2 0.96 4.12
1 0.98 4.13
0 1.00 4.14

Do you perhaps have any ideas? Or should I try another way for updating the OCP data?
Thank you for your support.

@valentinsulzer
Copy link
Member

The recommended way of doing this is to return PyBaMM's interpolant object

def U(sto):
    name = ...
    sto_data = ...
    U_data = ...
    return pybamm.Interpolant(sto_data, U_data, sto, name=name, interpolator="cubic")

@valentinsulzer valentinsulzer added the needs-reply Needs further information from the author and may be closed if no response is received label Oct 4, 2023
@yuchengluo1
Copy link
Author

Thanks for answering, it's very helpful!
I have one more question however. Could I update both cathode and anode OCP values together like down below or I should define U_cathode and U_anode separately?
def U(sto):
cathode_name = "cathode_ocp_interpolant"
anode_name = "anode_ocp_interpolant"

cathode_interpolant = pybamm.Interpolant(soc_cathode, u_cathode, sto, name=cathode_name, interpolator="cubic")
anode_interpolant = pybamm.Interpolant(soc_anode, u_anode, sto, name=anode_name, interpolator="cubic")

return cathode_interpolant, anode_interpolant

Thank you!

@github-actions github-actions bot removed the needs-reply Needs further information from the author and may be closed if no response is received label Oct 11, 2023
@valentinsulzer
Copy link
Member

they should be separate

@Tobi0211H
Copy link

Tobi0211H commented Apr 29, 2024

Hello everyone,
I am currently in the process of fitting a measured OCV as a function and working with it in Pyamm. I have seen that the standard OCVs in PyBaMM e.g. (Chen2020) are stored in this way. It is important to me that artifacts are not lost in the process. (e.g. phase transitions in graphite).
I started with this elaboration from the literature and corresponding source code:
https://pubs.acs.org/doi/pdf/10.1021/acs.jpclett.3c03129
https://github.com/BattModels
("Open-Circuit Voltage Models Should Be Thermodynamically
Consistent").

At the moment, however, I have the problem that the phase transition in the graphite is not as consistent as I would like.
If you compare my result with the fit of the anode OCV in Chen2020, you can see that this fit also represents the phase transition in the graphite excellently. I have not yet applied such a fit to my measurement.
The fitted function for the Pybamm data set is as follows:

def graphite_LGM50_ocp_Chen2020(sto): #Chen2020_composite
    """
    LG M50 Graphite open-circuit potential as a function of stochiometry, fit taken
    from [1].

    References
    ----------
    .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W.
    Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for
    Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the
    Electrochemical Society 167 (2020): 080534.

    Parameters
    ----------
    sto: :class:`pybamm.Symbol`
        Electrode stochiometry

    Returns
    -------
    :class:`pybamm.Symbol`
        Open-circuit potential
    """

    u_eq = (
        1.9793 * pybamm.exp(-39.3631 * sto)
        + 0.2482
        - 0.0909 * pybamm.tanh(29.8538 * (sto - 0.1234))
        - 0.04478 * pybamm.tanh(14.9159 * (sto - 0.2769))
        - 0.0205 * pybamm.tanh(30.4444 * (sto - 0.6103))
    )
    return u_eq

Now I wanted to ask if there is a "best" way to fit a custom OCV while preserving the actifacts and ensuring monotonicity.
Also, is there any additional material on the fit as implemented in Chen2020?

Thanks for the support.

@valentinsulzer
Copy link
Member

The options are:

  • Define your own functional form like the Chen2020 one and fit its parameters
  • Use an interpolant as above in this thread (possibly with some smoothing before hand, or fitting another model like the MSMR model to generate the interpolant)

There are other packages (open-source like pybop or commercial like Ionworks Lab) that can help with parameter fitting

@Tobi0211H
Copy link

Thank you very much.

@Tobi0211H
Copy link

Hello Valentin,
I have tried to fit my OCV with the conventional routines in Python, but I am not satisfied with the result. Within PyBaMM, many OCVs are stored as functions. So there must be a better way to perform the fit. My routines cannot cope with several tanh functions. Is there a standard procedure that I could use too?
I apologize for asking again, but unfortunately I can't get any further.

Thank you very much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants