Skip to content

Commit

Permalink
Merge branch 'develop' into telemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinsulzer committed Oct 28, 2024
2 parents 1a835a4 + 3864e5d commit 75d403d
Show file tree
Hide file tree
Showing 19 changed files with 620 additions and 148 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ci:

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.6.9"
rev: "v0.7.0"
hooks:
- id: ruff
args: [--fix, --show-fixes]
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Features

- Adds support to `pybamm.Experiment` for the `output_variables` option in the `IDAKLUSolver`. ([#4534](https://github.com/pybamm-team/PyBaMM/pull/4534))
- Adds an option "voltage as a state" that can be "false" (default) or "true". If "true" adds an explicit algebraic equation for the voltage. ([#4507](https://github.com/pybamm-team/PyBaMM/pull/4507))
- Improved `QuickPlot` accuracy for simulations with Hermite interpolation. ([#4483](https://github.com/pybamm-team/PyBaMM/pull/4483))
- Added Hermite interpolation to the (`IDAKLUSolver`) that improves the accuracy and performance of post-processing variables. ([#4464](https://github.com/pybamm-team/PyBaMM/pull/4464))
Expand All @@ -20,7 +21,7 @@
- Removed the `start_step_offset` setting and disabled minimum `dt` warnings for drive cycles with the (`IDAKLUSolver`). ([#4416](https://github.com/pybamm-team/PyBaMM/pull/4416))

## Bug Fixes

- Fixed bug in post-processing solutions with infeasible experiments using the (`IDAKLUSolver`). ([#4541](https://github.com/pybamm-team/PyBaMM/pull/4541))
- Disabled IREE on MacOS due to compatibility issues and added the CasADI
path to the environment to resolve issues on MacOS and Linux. Windows
users may still experience issues with interpolation. ([#4528](https://github.com/pybamm-team/PyBaMM/pull/4528))
Expand Down
4 changes: 2 additions & 2 deletions docs/source/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ API documentation
:Release: |version|
:Date: |today|

This reference manual details functions, modules, and objects
included in PyBaMM, describing what they are and what they do.
This reference manual details the classes, functions, modules, and objects included in PyBaMM, describing what they are and what they do.
For a high-level introduction to PyBaMM, see the :ref:`user guide <user_guide>` and the :ref:`examples <pybamm_examples>`.


.. toctree::
:maxdepth: 2

Expand Down
2 changes: 2 additions & 0 deletions docs/source/api/util.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ Utility functions
.. autofunction:: pybamm.has_jax

.. autofunction:: pybamm.is_jax_compatible

.. autofunction:: pybamm.set_logging_level

Large diffs are not rendered by default.

107 changes: 75 additions & 32 deletions docs/source/examples/notebooks/parameterization/parameter-values.ipynb

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions docs/source/user_guide/fundamentals/public_api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
----------
Public API
----------

.. module:: pybamm
:noindex:

PyBaMM is a Python package for mathematical modelling and simulation of battery systems. The main classes and functions that are intended to be used by the user are described in this document.
For a more detailed description of the classes and methods, see the :doc:`API reference </source/api/index>`.

Available PyBaMM models
-----------------------

PyBaMM includes a number of pre-implemented models, which can be used as they are or modified to suit your needs. The main models are:

- :class:`lithium_ion.SPM`: Single Particle Model
- :class:`lithium_ion.SPMe`: Single Particle Model with Electrolyte
- :class:`lithium_ion.DFN`: Doyle-Fuller-Newman

The behaviour of the models can be modified by passing in an :class:`BatteryModelOptions` object when creating the model.

Simulations
-----------

:class:`Simulation` is a class that automates the process of setting up a model and solving it, and acts as the highest-level API to PyBaMM.
Pass at least a :class:`BaseModel` object, and optionally the experiment, solver, parameter values, and geometry objects described below to the :class:`Simulation` object.
Any of these optional arguments not provided will be supplied by the defaults specified in the model.

Parameters
----------

PyBaMM models are parameterised by a set of parameters, which are stored in a :class:`ParameterValues` object. This object acts like a Python dictionary with a few extra PyBaMM specific features and methods.
Parameters in a model are represented as either :class:`Parameter` objects or :class:`FunctionParameter` objects, and the values in the :class:`ParameterValues` object replace these objects in the model before it is solved.
The values in the :class:`ParameterValues` object can be scalars, Python functions or expressions of type :class:`Symbol`.

Experiments
-----------

An :class:`Experiment` object represents an experimental protocol that can be used to simulate the behaviour of a battery. The particular protocol can be provided as a Python string, or as a sequences of
:class:`step.BaseStep` objects.

Solvers
-------

The two main solvers in PyBaMM are the :class:`CasadiSolver` and the :class:`IDAKLUSolver`. Both are wrappers around the Sundials suite of solvers, but the :class:`CasadiSolver` uses the CasADi library
whereas the :class:`IDAKLUSolver` is PyBaMM specific. Both solvers have many options that can be set to control the solver behaviour, see the documentation for each solver for more details.

When a model is solved, the solution is returned as a :class:`Solution` object.

Plotting
--------

A solution object can be plotted using the :meth:`Solution.plot` or :meth:`Simulation.plot` methods, which returns a :class:`QuickPlot` object.
Note that the arguments to the plotting methods of both classes are the same as :class:`QuickPlot`.

Other plotting functions are the :func:`plot_voltage_components` and :func:`plot_summary_variables` functions, which correspond to the similarly named methods of the :class:`Solution` and :class:`Simulation` classes.

Writing PyBaMM models
---------------------

Each PyBaMM model, and the custom models written by users, are written as a set of expressions that describe the model. Each of the expressions is a subclass of the :class:`Symbol` class, which represents a mathematical expression.

If you wish to create a custom model, you can use the :class:`BaseModel` class as a starting point.


Discretisation
--------------

Each PyBaMM model contains continuous operators that must be discretised before they can be solved. This is done using a :class:`Discretisation` object, which takes a :class:`Mesh` object and a dictionary of :class:`SpatialMethod` objects.

Logging
-------

PyBaMM uses the Python logging module to log messages at different levels of severity. Use the :func:`pybamm.set_logging_level` function to set the logging level for PyBaMM.
1 change: 1 addition & 0 deletions docs/source/user_guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ maxdepth: 2
---
fundamentals/index
fundamentals/battery_models
fundamentals/public_api
```

```{toctree}
Expand Down
11 changes: 11 additions & 0 deletions src/pybamm/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ def func(self, message, *args, **kws):


def set_logging_level(level):
"""
Set the logging level for PyBaMM
Parameters
----------
level: str
The logging level to set. Should be one of 'DEBUG', 'INFO', 'WARNING',
'ERROR', 'CRITICAL'
"""
logger.setLevel(level)


Expand Down
1 change: 1 addition & 0 deletions src/pybamm/solvers/base_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,7 @@ def get_termination_reason(solution, events):
solution.t_event,
solution.y_event,
solution.termination,
variables_returned=solution.variables_returned,
)
event_sol.solve_time = 0
event_sol.integration_time = 0
Expand Down
9 changes: 9 additions & 0 deletions src/pybamm/solvers/c_solvers/idaklu/observe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class TimeSeriesInterpolator {
) {
for (size_t i = 0; i < ts_data_np.size(); i++) {
const auto& t_data = ts_data_np[i].unchecked<1>();
// Continue if there is no data
if (t_data.size() == 0) {
continue;
}

const realtype t_data_final = t_data(t_data.size() - 1);
realtype t_interp_next = t_interp(i_interp);
// Continue if the next interpolation point is beyond the final data point
Expand Down Expand Up @@ -227,6 +232,10 @@ class TimeSeriesProcessor {
int i_entries = 0;
for (size_t i = 0; i < ts.size(); i++) {
const auto& t = ts[i].unchecked<1>();
// Continue if there is no data
if (t.size() == 0) {
continue;
}
const auto& y = ys[i].unchecked<2>();
const auto input = inputs[i].data();
const auto func = *funcs[i];
Expand Down
1 change: 1 addition & 0 deletions src/pybamm/solvers/idaklu_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,7 @@ def _post_process_solution(self, sol, model, integration_time, inputs_dict):
termination,
all_sensitivities=yS_out,
all_yps=yp,
variables_returned=bool(save_outputs_only),
)

newsol.integration_time = integration_time
Expand Down
31 changes: 15 additions & 16 deletions src/pybamm/solvers/processed_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,22 @@ def _setup_cpp_inputs(self, t, full_range):
ys = self.all_ys
yps = self.all_yps
inputs = self.all_inputs_casadi
# Find the indices of the time points to observe
if full_range:
idxs = range(len(ts))
else:
idxs = _find_ts_indices(ts, t)

if isinstance(idxs, list):
# Extract the time points and inputs
ts = [ts[idx] for idx in idxs]
ys = [ys[idx] for idx in idxs]
if self.hermite_interpolation:
yps = [yps[idx] for idx in idxs]
inputs = [self.all_inputs_casadi[idx] for idx in idxs]
# Remove all empty ts
idxs = np.where([ti.size > 0 for ti in ts])[0]

# Find the indices of the time points to observe
if not full_range:
ts_nonempty = [ts[idx] for idx in idxs]
idxs_subset = _find_ts_indices(ts_nonempty, t)
idxs = idxs[idxs_subset]

# Extract the time points and inputs
ts = [ts[idx] for idx in idxs]
ys = [ys[idx] for idx in idxs]
if self.hermite_interpolation:
yps = [yps[idx] for idx in idxs]
inputs = [self.all_inputs_casadi[idx] for idx in idxs]

is_f_contiguous = _is_f_contiguous(ys)

Expand Down Expand Up @@ -977,8 +980,4 @@ def _find_ts_indices(ts, t):
if (t[-1] > ts[-1][-1]) and (len(indices) == 0 or indices[-1] != len(ts) - 1):
indices.append(len(ts) - 1)

if len(indices) == len(ts):
# All indices are included
return range(len(ts))

return indices
27 changes: 26 additions & 1 deletion src/pybamm/solvers/processed_variable_computed.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#
# Processed Variable class
# Processed Variable Computed class
#
from __future__ import annotations
import casadi
import numpy as np
import pybamm
Expand Down Expand Up @@ -450,3 +451,27 @@ def sensitivities(self):
if len(self.all_inputs[0]) == 0:
return {}
return self._sensitivities

def _update(
self, other: pybamm.ProcessedVariableComputed, new_sol: pybamm.Solution
) -> pybamm.ProcessedVariableComputed:
"""
Returns a new ProcessedVariableComputed object that is the result of appending
the data from other to this object. Used exclusively in running experiments, to
append the data from one cycle to the next.
Parameters
----------
other : :class:`pybamm.ProcessedVariableComputed`
The other ProcessedVariableComputed object to append to this one
new_sol : :class:`pybamm.Solution`
The new solution object to be used to create the processed variables
"""

bv = self.base_variables + other.base_variables
bvc = self.base_variables_casadi + other.base_variables_casadi
bvd = self.base_variables_data + other.base_variables_data

new_var = self.__class__(bv, bvc, bvd, new_sol)

return new_var
Loading

0 comments on commit 75d403d

Please sign in to comment.