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

Implement GITT example #249

Merged
merged 36 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c8069ba
#223 refactor problems into problem folder
brosaplanella Mar 17, 2024
f380ea4
add Weppner & Huggins model, with some hacks to make it work
brosaplanella Mar 20, 2024
e83d6b3
add GITT FittingProblem
brosaplanella Mar 20, 2024
575c27e
add GITT example
brosaplanella Mar 20, 2024
ab34b4d
Merge branch 'develop' into issue-223-GITT
brosaplanella Mar 20, 2024
7b53b75
style: pre-commit fixes
pre-commit-ci[bot] Mar 20, 2024
659c98e
#223 fix typo
brosaplanella Mar 25, 2024
d98349a
#223 rename example
brosaplanella Mar 25, 2024
4cbac89
#223 add unit test GITT
brosaplanella Mar 25, 2024
feae75b
Merge remote-tracking branch 'upstream/develop' into issue-223-GITT
brosaplanella Mar 25, 2024
b586aac
style: pre-commit fixes
pre-commit-ci[bot] Mar 25, 2024
d583f1d
#223 import pybop
brosaplanella Mar 25, 2024
cef8cc2
style: pre-commit fixes
pre-commit-ci[bot] Mar 25, 2024
6ab1378
#223 comment out failing test to check coverage
brosaplanella Mar 25, 2024
d17b1f7
Merge branch 'issue-223-GITT' of github.com:brosaplanella/PyBOP into …
brosaplanella Mar 25, 2024
b85dbcb
#223 fix ruff
brosaplanella Mar 25, 2024
d447d66
#223 fix failing example
brosaplanella Mar 30, 2024
da4ff8b
Apply suggestions from code review
brosaplanella Apr 8, 2024
d4bf431
#223 fix typo
brosaplanella Apr 8, 2024
edb5e18
remove duplicated parameters
brosaplanella Apr 8, 2024
c4e88d4
#223 add citation
brosaplanella Apr 8, 2024
1e49571
Merge remote-tracking branch 'upstream/develop' into issue-223-GITT
brosaplanella Apr 8, 2024
8ae2f19
style: pre-commit fixes
pre-commit-ci[bot] Apr 8, 2024
74972bc
ruff
brosaplanella Apr 8, 2024
a9d57c5
#223 fix failing tests
brosaplanella Apr 8, 2024
2f6a0e7
style: pre-commit fixes
pre-commit-ci[bot] Apr 8, 2024
c505c41
Merge branch 'develop' into issue-223-GITT
brosaplanella Apr 14, 2024
c126ee2
Merge remote-tracking branch 'upstream/develop' into issue-223-GITT
brosaplanella May 15, 2024
3e1b601
#223 get surface area to volume ratio from PyBaMM
brosaplanella May 15, 2024
6a5ee3d
#223 reverted change as surface area per unit volume is a variable
brosaplanella May 15, 2024
d38b38f
#223 remove GITT class and move to example
brosaplanella May 15, 2024
0a646f8
#223 update CHANGELOG
brosaplanella May 15, 2024
20d3612
#223 remove references to GITT class
brosaplanella May 15, 2024
fdbc803
#223 add credit to pbparam team
brosaplanella May 15, 2024
1ab30d4
#223 add tests for WeppnerHuggins
brosaplanella May 16, 2024
d91c1e5
style: pre-commit fixes
pre-commit-ci[bot] May 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Features

- [#249](https://github.com/pybop-team/PyBOP/pull/249) - Add WeppnerHuggins model and GITT example.
- [#304](https://github.com/pybop-team/PyBOP/pull/304) - Decreases the testing suite completion time.
- [#301](https://github.com/pybop-team/PyBOP/pull/301) - Updates default echem solver to "fast with events" mode.
- [#251](https://github.com/pybop-team/PyBOP/pull/251) - Increment PyBaMM > v23.5, remove redundant tests within integration tests, increment citation version, fix examples with incorrect model definitions.
Expand Down
70 changes: 70 additions & 0 deletions examples/scripts/gitt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import numpy as np

import pybop

# Define model
parameter_set = pybop.ParameterSet.pybamm("Xu2019")
model = pybop.lithium_ion.SPM(
parameter_set=parameter_set, options={"working electrode": "positive"}
)

# Generate data
sigma = 0.005
t_eval = np.arange(0, 150, 2)
values = model.predict(t_eval=t_eval)
corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval))

# Form dataset
dataset = pybop.Dataset(
{
"Time [s]": t_eval,
"Current function [A]": values["Current [A]"].data,
"Voltage [V]": corrupt_values,
}
)

# Define parameter set
parameter_set.update(
{
"Reference OCP [V]": 4.1821,
"Derivative of the OCP wrt stoichiometry [V]": -1.38636,
},
check_already_exists=False,
)

# Define the cost to optimise
model = pybop.lithium_ion.WeppnerHuggins(parameter_set=parameter_set)

parameters = [
pybop.Parameter(
"Positive electrode diffusivity [m2.s-1]",
prior=pybop.Gaussian(5e-14, 1e-13),
bounds=[1e-16, 1e-11],
true_value=parameter_set["Positive electrode diffusivity [m2.s-1]"],
),
]

problem = pybop.FittingProblem(
model,
parameters,
dataset,
signal=["Voltage [V]"],
)

cost = pybop.RootMeanSquaredError(problem)

# Build the optimisation problem
optim = pybop.Optimisation(cost=cost, optimiser=pybop.PSO, verbose=True)

# Run the optimisation problem
x, final_cost = optim.run()
print("Estimated parameters:", x)

# Plot the timeseries output
pybop.quick_plot(problem, parameter_values=x, title="Optimised Comparison")

# Plot convergence
pybop.plot_convergence(optim)

# Plot the parameter traces
pybop.plot_parameters(optim)
3 changes: 1 addition & 2 deletions pybop/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
from ._utils import is_numeric

#
# Cost class
# Problem class
# Problem classes
#
from .problems.base_problem import BaseProblem
from .problems.fitting_problem import FittingProblem
Expand Down
2 changes: 1 addition & 1 deletion pybop/models/lithium_ion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Import lithium ion based models
#
from .base_echem import EChemBaseModel
from .echem import SPM, SPMe, DFN, MPM, MSMR
from .echem import SPM, SPMe, DFN, MPM, MSMR, WeppnerHuggins
28 changes: 18 additions & 10 deletions pybop/models/lithium_ion/base_echem.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,24 @@
"""
parameter_set = parameter_set or self._parameter_set

electrode_params = [
(
"Negative electrode active material volume fraction",
"Negative electrode porosity",
),
(
"Positive electrode active material volume fraction",
"Positive electrode porosity",
),
]
if self.pybamm_model.options["working electrode"] == "positive":
electrode_params = [

Check warning on line 77 in pybop/models/lithium_ion/base_echem.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/base_echem.py#L77

Added line #L77 was not covered by tests
(
"Positive electrode active material volume fraction",
"Positive electrode porosity",
),
]
else:
electrode_params = [
(
"Negative electrode active material volume fraction",
"Negative electrode porosity",
),
(
"Positive electrode active material volume fraction",
"Positive electrode porosity",
),
]

related_parameters = {
key: inputs.get(key) if inputs and key in inputs else parameter_set[key]
Expand Down
48 changes: 48 additions & 0 deletions pybop/models/lithium_ion/echem.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pybamm

from .base_echem import EChemBaseModel
from .weppner_huggins import BaseWeppnerHuggins


class SPM(EChemBaseModel):
Expand Down Expand Up @@ -270,3 +271,50 @@
spatial_methods=spatial_methods,
solver=solver,
)


class WeppnerHuggins(EChemBaseModel):
"""
Represents the Weppner & Huggins model to fit diffusion coefficients to GITT data.

Parameters
----------
name: str, optional
A name for the model instance, defaults to "Weppner & Huggins model".
parameter_set: pybamm.ParameterValues or dict, optional
A dictionary or a ParameterValues object containing the parameters for the model. If None, the default parameters are used.
geometry: dict, optional
A dictionary defining the model's geometry. If None, the default geometry is used.
submesh_types: dict, optional
A dictionary defining the types of submeshes to use. If None, the default submesh types are used.
var_pts: dict, optional
A dictionary specifying the number of points for each variable for discretization. If None, the default variable points are used.
spatial_methods: dict, optional
A dictionary specifying the spatial methods for discretization. If None, the default spatial methods are used.
solver: pybamm.Solver, optional
The solver to use for simulating the model. If None, the default solver is used.
"""

def __init__(
self,
name="Weppner & Huggins model",
parameter_set=None,
geometry=None,
submesh_types=None,
var_pts=None,
spatial_methods=None,
solver=None,
):
self.pybamm_model = BaseWeppnerHuggins()
self._unprocessed_model = self.pybamm_model

Check warning on line 309 in pybop/models/lithium_ion/echem.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/echem.py#L308-L309

Added lines #L308 - L309 were not covered by tests

super().__init__(

Check warning on line 311 in pybop/models/lithium_ion/echem.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/echem.py#L311

Added line #L311 was not covered by tests
model=self.pybamm_model,
name=name,
parameter_set=parameter_set,
geometry=geometry,
submesh_types=submesh_types,
var_pts=var_pts,
spatial_methods=spatial_methods,
solver=solver,
)
100 changes: 100 additions & 0 deletions pybop/models/lithium_ion/weppner_huggins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#
# Weppner Huggins Model
#
import numpy as np
import pybamm


class BaseWeppnerHuggins(pybamm.lithium_ion.BaseModel):
"""WeppnerHuggins Model for GITT.

Parameters
brosaplanella marked this conversation as resolved.
Show resolved Hide resolved
----------
name : str, optional
The name of the model.
"""

def __init__(self, name="Weppner & Huggins model"):
super().__init__({}, name)

Check warning on line 18 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L18

Added line #L18 was not covered by tests

pybamm.citations.register("""

Check warning on line 20 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L20

Added line #L20 was not covered by tests
@article{Weppner1977,
title={{Determination of the kinetic parameters
of mixed-conducting electrodes and application to the system Li3Sb}},
author={Weppner, W and Huggins, R A},
journal={Journal of The Electrochemical Society},
volume={124},
number={10},
pages={1569},
year={1977},
publisher={IOP Publishing}
}
""")

# `self.param` is a class containing all the relevant parameters and functions for
# this model. These are purely symbolic at this stage, and will be set by the
# `ParameterValues` class when the model is processed.
self.options["working electrode"] = "positive"

Check warning on line 37 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L37

Added line #L37 was not covered by tests

t = pybamm.t

Check warning on line 39 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L39

Added line #L39 was not covered by tests
######################
# Parameters
######################

d_s = pybamm.Parameter("Positive electrode diffusivity [m2.s-1]")

Check warning on line 44 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L44

Added line #L44 was not covered by tests

c_s_max = pybamm.Parameter(

Check warning on line 46 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L46

Added line #L46 was not covered by tests
"Maximum concentration in positive electrode [mol.m-3]"
)

i_app = self.param.current_density_with_time

Check warning on line 50 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L50

Added line #L50 was not covered by tests

U = pybamm.Parameter("Reference OCP [V]")

Check warning on line 52 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L52

Added line #L52 was not covered by tests

U_prime = pybamm.Parameter("Derivative of the OCP wrt stoichiometry [V]")

Check warning on line 54 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L54

Added line #L54 was not covered by tests

epsilon = pybamm.Parameter("Positive electrode active material volume fraction")

Check warning on line 56 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L56

Added line #L56 was not covered by tests

r_particle = pybamm.Parameter("Positive particle radius [m]")

Check warning on line 58 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L58

Added line #L58 was not covered by tests

a = 3 * (epsilon / r_particle)

Check warning on line 60 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L60

Added line #L60 was not covered by tests
BradyPlanden marked this conversation as resolved.
Show resolved Hide resolved

l_w = self.param.p.L

Check warning on line 62 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L62

Added line #L62 was not covered by tests

######################
# Governing equations
######################
u_surf = (

Check warning on line 67 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L67

Added line #L67 was not covered by tests
(2 / (np.pi**0.5))
* (i_app / ((d_s**0.5) * a * self.param.F * l_w))
* (t**0.5)
)
# Linearised voltage
V = U + (U_prime * u_surf) / c_s_max

Check warning on line 73 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L73

Added line #L73 was not covered by tests
######################
# (Some) variables
######################
self.variables = {

Check warning on line 77 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L77

Added line #L77 was not covered by tests
"Voltage [V]": V,
"Time [s]": t,
}

@property
def default_geometry(self):
return {}

Check warning on line 84 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L84

Added line #L84 was not covered by tests

@property
def default_submesh_types(self):
return {}

Check warning on line 88 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L88

Added line #L88 was not covered by tests

@property
def default_var_pts(self):
return {}

Check warning on line 92 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L92

Added line #L92 was not covered by tests

@property
def default_spatial_methods(self):
return {}

Check warning on line 96 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L96

Added line #L96 was not covered by tests

@property
def default_solver(self):
return pybamm.DummySolver()

Check warning on line 100 in pybop/models/lithium_ion/weppner_huggins.py

View check run for this annotation

Codecov / codecov/patch

pybop/models/lithium_ion/weppner_huggins.py#L100

Added line #L100 was not covered by tests
Loading