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

add unit benchmarks #2092

Merged
merged 3 commits into from
Jun 15, 2022
Merged
Changes from 1 commit
Commits
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
98 changes: 98 additions & 0 deletions benchmarks/unit_benchmarks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import pybamm
import numpy as np

R = 1e-5


def time_create_expression():
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should define a class like with the other benchmarks. The first bit can be pushed under the setup method, and then have the different benchmarks.

global model
model = pybamm.BaseModel()

R = pybamm.Parameter("Particle radius [m]")
D = pybamm.Parameter("Diffusion coefficient [m2.s-1]")
j = pybamm.Parameter("Interfacial current density [A.m-2]")
F = pybamm.Parameter("Faraday constant [C.mol-1]")
c0 = pybamm.Parameter("Initial concentration [mol.m-3]")

c = pybamm.Variable("Concentration [mol.m-3]", domain="negative particle")
N = -D * pybamm.grad(c)
dcdt = -pybamm.div(N)
model.rhs = {c: dcdt}

lbc = pybamm.Scalar(0)
rbc = -j / F / D
model.boundary_conditions = {
c: {"left": (lbc, "Neumann"), "right": (rbc, "Neumann")}
}

model.initial_conditions = {c: c0}
model.variables = {
"Concentration [mol.m-3]": c,
"Surface concentration [mol.m-3]": pybamm.surf(c),
"Flux [mol.m-2.s-1]": N,
}


def setup_parameterise():
time_create_expression()


def time_parameterise():

global param
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should be able to do this without using global. I have never seen a good reason to use it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The benchmarks don't work without these global variables even after adding the setup functions. I don't know why this is the case, but when I run the benchmarks with the global variables they work

param = pybamm.ParameterValues(
{
"Particle radius [m]": 10e-6,
"Diffusion coefficient [m2.s-1]": 3.9e-14,
"Interfacial current density [A.m-2]": 1.4,
"Faraday constant [C.mol-1]": 96485,
"Initial concentration [mol.m-3]": 2.5e4,
}
)
global r
r = pybamm.SpatialVariable(
"r", domain=["negative particle"], coord_sys="spherical polar"
)
global geometry
geometry = {"negative particle": {r: {"min": pybamm.Scalar(0), "max": R}}}
param.process_model(model)
param.process_geometry(geometry)


time_parameterise.setup = setup_parameterise


def setup_discretise():
time_create_expression()
time_parameterise()


def time_discretise():
time_create_expression()
time_parameterise()

submesh_types = {"negative particle": pybamm.Uniform1DSubMesh}
var_pts = {r: 20}
mesh = pybamm.Mesh(geometry, submesh_types, var_pts)

spatial_methods = {"negative particle": pybamm.FiniteVolume()}
disc = pybamm.Discretisation(mesh, spatial_methods)
disc.process_model(model)


time_discretise.setup = setup_discretise


def setup_solve():
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The discretisation and parameterisation methods modify the model, so if you define model to be a variable of the class then hopefully you do not need to initialise every single time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this but got an error because asv runs every method separately, so the changes made in one method don't carry on to others. For example-
for the time_solve benchmark to work we will need to run previous methods in its setup, and a class cannot have more than 1 setup; hence, I cannot put this under the class containing other time_* functions as they require a different setup

time_create_expression()
time_parameterise()
time_discretise()


def time_solve():
solver = pybamm.ScipySolver()
t = np.linspace(0, 3600, 600)
solver.solve(model, t)


time_solve.setup = setup_solve