From 346bda7b343d691f7918f46beb1feb1916c07a59 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:57:24 +0100 Subject: [PATCH 1/5] Create functional_parameters.py --- examples/scripts/functional_parameters.py | 90 +++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 examples/scripts/functional_parameters.py diff --git a/examples/scripts/functional_parameters.py b/examples/scripts/functional_parameters.py new file mode 100644 index 000000000..37f821020 --- /dev/null +++ b/examples/scripts/functional_parameters.py @@ -0,0 +1,90 @@ +import numpy as np +import pybop +import pybamm + + +# This example demonstrates how to use a pybamm.FunctionalParameter to +# optimise functional parameters using PyBOP. + +# Method: Define a new constant parameter for use in a functional parameter +# that already exists in the model, for example an exchange current density. + + +# Parameter set and model definition +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + +# Define a new function using new parameters +def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): + # New parameters + j0_ref = pybamm.Parameter( + "Positive electrode reference exchange-current density [A.m-2]" + ) + alpha = pybamm.Parameter("Positive electrode charge transfer coefficient") + + # Existing parameters + c_e_init = pybamm.Parameter("Initial concentration in electrolyte [mol.m-3]") + + return ( + j0_ref + * ((c_e / c_e_init) * (c_s_surf / c_s_max) * (1 - c_s_surf / c_s_max)) ** alpha + ) + + +# Give default values to the new constant parameters and pass the new function +parameter_set.update( + { + "Positive electrode reference exchange-current density [A.m-2]": 1, + "Positive electrode charge transfer coefficient": 0.5, + }, + check_already_exists=False, +) +parameter_set["Positive electrode exchange-current density [A.m-2]"] = positive_electrode_exchange_current_density + +# Fitting parameters +parameters = pybop.Parameters( + pybop.Parameter( + "Positive electrode reference exchange-current density [A.m-2]", + prior=pybop.Gaussian(1, 0.1), + ), + pybop.Parameter( + "Positive electrode charge transfer coefficient", + prior=pybop.Gaussian(0.5, 0.1), + ), +) + +# Generate data +sigma = 0.001 +t_eval = np.arange(0, 900, 3) +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, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.RootMeanSquaredError(problem) +optim = pybop.SciPyMinimize(cost,max_iterations=125) + +# Run optimisation +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(problem, problem_inputs=x, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape with optimisation path +pybop.plot2d(optim, steps=15) From 499c80eac4e3a434cd58731c284414028ac9ddcd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 10:59:25 +0000 Subject: [PATCH 2/5] style: pre-commit fixes --- examples/scripts/functional_parameters.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/scripts/functional_parameters.py b/examples/scripts/functional_parameters.py index 37f821020..cc2d9e4da 100644 --- a/examples/scripts/functional_parameters.py +++ b/examples/scripts/functional_parameters.py @@ -1,7 +1,7 @@ import numpy as np -import pybop import pybamm +import pybop # This example demonstrates how to use a pybamm.FunctionalParameter to # optimise functional parameters using PyBOP. @@ -14,6 +14,7 @@ parameter_set = pybop.ParameterSet.pybamm("Chen2020") model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + # Define a new function using new parameters def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): # New parameters @@ -39,7 +40,9 @@ def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): }, check_already_exists=False, ) -parameter_set["Positive electrode exchange-current density [A.m-2]"] = positive_electrode_exchange_current_density +parameter_set["Positive electrode exchange-current density [A.m-2]"] = ( + positive_electrode_exchange_current_density +) # Fitting parameters parameters = pybop.Parameters( @@ -71,7 +74,7 @@ def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): # Generate problem, cost function, and optimisation class problem = pybop.FittingProblem(model, parameters, dataset) cost = pybop.RootMeanSquaredError(problem) -optim = pybop.SciPyMinimize(cost,max_iterations=125) +optim = pybop.SciPyMinimize(cost, max_iterations=125) # Run optimisation x, final_cost = optim.run() From 4b82c78fdbe7b67ac3d057ff7c5565de2dc74fd7 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:24:03 +0100 Subject: [PATCH 3/5] Define parameter set first --- examples/scripts/functional_parameters.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/scripts/functional_parameters.py b/examples/scripts/functional_parameters.py index cc2d9e4da..60071e080 100644 --- a/examples/scripts/functional_parameters.py +++ b/examples/scripts/functional_parameters.py @@ -10,9 +10,8 @@ # that already exists in the model, for example an exchange current density. -# Parameter set and model definition +# Load default parameter set parameter_set = pybop.ParameterSet.pybamm("Chen2020") -model = pybop.lithium_ion.SPM(parameter_set=parameter_set) # Define a new function using new parameters @@ -44,6 +43,11 @@ def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): positive_electrode_exchange_current_density ) +# Model definition +model = pybop.lithium_ion.SPM( + parameter_set=parameter_set, options={"contact resistance": "true"} +) + # Fitting parameters parameters = pybop.Parameters( pybop.Parameter( From 69f02ecae8dd055b3624e1176aba2ce2f69a837c Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:27:56 +0100 Subject: [PATCH 4/5] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b6d4f96a..84e601fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Features +- [#441](https://github.com/pybop-team/PyBOP/issues/441) - Adds an example for estimating constants within a `pybamm.FunctionalParameter`. - [#418](https://github.com/pybop-team/PyBOP/issues/418) - Wraps the `get_parameter_info` method from PyBaMM to get a dictionary of parameter names and types. - [#413](https://github.com/pybop-team/PyBOP/pull/413) - Adds `DesignCost` functionality to `WeightedCost` class with additional tests. - [#357](https://github.com/pybop-team/PyBOP/pull/357) - Adds `Transformation()` class with `LogTransformation()`, `IdentityTransformation()`, and `ScaledTransformation()`, `ComposedTransformation()` implementations with corresponding examples and tests. From 6783703f861252aefd4b29dbda671b234188eda3 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:55:38 +0100 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Brady Planden <55357039+BradyPlanden@users.noreply.github.com> --- examples/scripts/functional_parameters.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/scripts/functional_parameters.py b/examples/scripts/functional_parameters.py index 60071e080..39b179c0f 100644 --- a/examples/scripts/functional_parameters.py +++ b/examples/scripts/functional_parameters.py @@ -6,15 +6,15 @@ # This example demonstrates how to use a pybamm.FunctionalParameter to # optimise functional parameters using PyBOP. -# Method: Define a new constant parameter for use in a functional parameter +# Method: Define a new scalar parameter for use in a functional parameter # that already exists in the model, for example an exchange current density. -# Load default parameter set +# Load parameter set parameter_set = pybop.ParameterSet.pybamm("Chen2020") -# Define a new function using new parameters +# Define a new function using pybamm parameters def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): # New parameters j0_ref = pybamm.Parameter( @@ -31,7 +31,7 @@ def positive_electrode_exchange_current_density(c_e, c_s_surf, c_s_max, T): ) -# Give default values to the new constant parameters and pass the new function +# Give default values to the new scalar parameters and pass the new function parameter_set.update( { "Positive electrode reference exchange-current density [A.m-2]": 1,