Source code for pybop.problems.fitting_problem

import numpy as np

from pybop import BaseProblem
from pybop.parameters.parameter import Inputs


[docs] class FittingProblem(BaseProblem): """ Problem class for fitting (parameter estimation) problems. Extends `BaseProblem` with specifics for fitting a model to a dataset. Parameters ---------- model : object The model to fit. parameters : pybop.Parameter or pybop.Parameters An object or list of the parameters for the problem. dataset : Dataset Dataset object containing the data to fit the model to. signal : str, optional The variable used for fitting (default: "Voltage [V]"). additional_variables : List[str], optional Additional variables to observe and store in the solution (default additions are: ["Time [s]"]). init_soc : float, optional Initial state of charge (default: None). """ def __init__( self, model, parameters, dataset, check_model=True, signal=["Voltage [V]"], additional_variables=[], init_soc=None, ): # Add time and remove duplicates additional_variables.extend(["Time [s]"])
[docs] additional_variables = list(set(additional_variables))
super().__init__( parameters, model, check_model, signal, additional_variables, init_soc )
[docs] self._dataset = dataset.data
self.parameters.initial_value() # Check that the dataset contains time and current dataset.check(self.signal + ["Current function [A]"]) # Unpack time and target data
[docs] self._time_data = self._dataset["Time [s]"]
[docs] self.n_time_data = len(self._time_data)
self.set_target(dataset) # Add useful parameters to model if model is not None: self._model.signal = self.signal self._model.additional_variables = self.additional_variables self._model.n_outputs = self.n_outputs self._model.n_time_data = self.n_time_data # Build the model from scratch if self._model._built_model is not None: self._model._model_with_set_params = None self._model._built_model = None self._model._built_initial_soc = None self._model._mesh = None self._model._disc = None self._model.build( dataset=self._dataset, parameters=self.parameters, check_model=self.check_model, init_soc=self.init_soc, )
[docs] def evaluate(self, inputs: Inputs): """ Evaluate the model with the given parameters and return the signal. Parameters ---------- inputs : Inputs Parameters for evaluation of the model. Returns ------- y : np.ndarray The model output y(t) simulated with given inputs. """ inputs = self.parameters.verify(inputs) requires_rebuild = False for key, value in inputs.items(): if key in self._model.rebuild_parameters: current_value = self.parameters[key].value if value != current_value: self.parameters[key].update(value=value) requires_rebuild = True if requires_rebuild: self._model.rebuild(parameters=self.parameters) y = self._model.simulate(inputs=inputs, t_eval=self._time_data) return y
[docs] def evaluateS1(self, inputs: Inputs): """ Evaluate the model with the given parameters and return the signal and its derivatives. Parameters ---------- inputs : Inputs Parameters for evaluation of the model. Returns ------- tuple A tuple containing the simulation result y(t) and the sensitivities dy/dx(t) evaluated with given inputs. """ inputs = self.parameters.verify(inputs) if self._model.rebuild_parameters: raise RuntimeError( "Gradient not available when using geometric parameters." ) y, dy = self._model.simulateS1( inputs=inputs, t_eval=self._time_data, ) return (y, np.asarray(dy))