├── src └── pybamm_cookie │ ├── py.typed │ ├── __main__.py │ ├── version.pyi │ ├── __init__.py │ └── cli.py ├── template └── {{ project_name }} │ ├── docs │ ├── refs.bib │ ├── _static │ │ └── .gitkeep │ ├── index.md.jinja │ └── conf.py.jinja │ ├── src │ └── {{project_slug}} │ │ ├── {% if mypy %}py.typed{% endif %} │ │ ├── {% if vcs %}_version.py{% endif %} │ │ ├── __init__.py.jinja │ │ ├── entry_point.py.jinja │ │ ├── models │ │ └── input │ │ │ ├── BasicReservoir.py │ │ │ └── SPM.py │ │ └── parameters │ │ └── input │ │ └── Chen2020.py │ ├── {% if ci == 'gitlab' %}.gitlab-ci.yml{% endif %}.jinja │ ├── {% if vcs == true %}.gitattributes.txt{% endif %}.jinja │ ├── .copier-answers.yml.jinja │ ├── tests │ ├── user_tests │ │ └── test_package.py.jinja │ └── generated_project_tests │ │ └── test_entry_points.py.jinja │ ├── {% if backend == 'setuptools' and vcs == false %}MANIFEST.in{% endif %}.jinja │ ├── {% if vcs == true %}.git_archival.txt{% endif %}.jinja │ ├── {% if ci == 'github' %}.github{% endif %} │ ├── dependabot.yml │ └── workflows │ │ └── test_on_push.yml │ ├── LICENSES-bundled.txt.jinja │ ├── .readthedocs.yml │ ├── {% if license=='MIT' %}LICENSE{% endif %}.jinja │ ├── README.md.jinja │ ├── {% if license=='BSD' %}LICENSE{% endif %}.jinja │ ├── .pre-commit-config.yaml.jinja │ ├── .gitignore │ ├── noxfile.py.jinja │ ├── pyproject.toml.jinja │ └── {% if license=='Apache' %}LICENSE{% endif %}.jinja ├── gitattributes.txt ├── docs ├── _static │ ├── pybammcookie.png │ └── pybammcookiewhite.png ├── index.md └── conf.py ├── git_archival.txt ├── .github ├── codecov.yml ├── dependabot.yml └── workflows │ ├── release.yml │ └── test_on_push.yml ├── .readthedocs.yml ├── LICENSE ├── .pre-commit-config.yaml ├── tests └── template_tests │ └── test_project_generation.py ├── noxfile.py ├── copier.yml ├── .gitignore ├── pyproject.toml ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md └── README.md /src/pybamm_cookie/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/{{ project_name }}/docs/refs.bib: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gitattributes.txt: -------------------------------------------------------------------------------- 1 | .git_archival.txt export-subst 2 | -------------------------------------------------------------------------------- /template/{{ project_name }}/docs/_static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/{% if mypy %}py.typed{% endif %}: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if ci == 'gitlab' %}.gitlab-ci.yml{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if vcs == true %}.gitattributes.txt{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | .git_archival.txt export-subst 2 | -------------------------------------------------------------------------------- /docs/_static/pybammcookie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pybamm-team/pybamm-cookie/HEAD/docs/_static/pybammcookie.png -------------------------------------------------------------------------------- /docs/_static/pybammcookiewhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pybamm-team/pybamm-cookie/HEAD/docs/_static/pybammcookiewhite.png -------------------------------------------------------------------------------- /src/pybamm_cookie/__main__.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | from pybamm_cookie.cli import pybamm_cookie_cli 3 | 4 | pybamm_cookie_cli() 5 | -------------------------------------------------------------------------------- /git_archival.txt: -------------------------------------------------------------------------------- 1 | node: $Format:%H$ 2 | node-date: $Format:%cI$ 3 | describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ 4 | ref-names: $Format:%D$ 5 | -------------------------------------------------------------------------------- /src/pybamm_cookie/version.pyi: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | version: str 4 | version_tuple: tuple[int, int, int] | tuple[int, int, int, str, str] 5 | -------------------------------------------------------------------------------- /template/{{ project_name }}/.copier-answers.yml.jinja: -------------------------------------------------------------------------------- 1 | # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY 2 | {{ _copier_answers|to_nice_yaml -}} 3 | -------------------------------------------------------------------------------- /template/{{ project_name }}/tests/user_tests/test_package.py.jinja: -------------------------------------------------------------------------------- 1 | import {{ project_slug }} as m 2 | 3 | 4 | def test_version(): 5 | assert m.__version__ 6 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if backend == 'setuptools' and vcs == false %}MANIFEST.in{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | graft src 2 | prune tests 3 | 4 | global-exclude __pycache__ *.py[cod] .venv .copier-answers.yml 5 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/{% if vcs %}_version.py{% endif %}: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | version: str 4 | version_tuple: tuple[int, int, int] | tuple[int, int, int, str, str] 5 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if vcs == true %}.git_archival.txt{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | node: $Format:%H$ 2 | node-date: $Format:%cI$ 3 | describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ 4 | ref-names: $Format:%D$ 5 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | token: ${{ secrets.CODECOV_TOKEN }} 3 | ci: 4 | - "test_on_push" 5 | strict_yaml_branch: "main" 6 | disable_default_path_fixes: no 7 | require_ci_to_pass: yes 8 | 9 | github_checks: 10 | annotations: true 11 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # pybamm-cookie 2 | 3 | ```{toctree} 4 | :maxdepth: 2 5 | :hidden: 6 | 7 | ``` 8 | 9 | ```{include} ../README.md 10 | :start-after: 11 | :end-before: 12 | ``` 13 | 14 | ## Indices and tables 15 | 16 | - {ref}`genindex` 17 | - {ref}`modindex` 18 | - {ref}`search` 19 | -------------------------------------------------------------------------------- /template/{{ project_name }}/docs/index.md.jinja: -------------------------------------------------------------------------------- 1 | # {{ project_name }} 2 | 3 | ```{toctree} 4 | :maxdepth: 2 5 | :hidden: 6 | 7 | ``` 8 | 9 | ```{include} ../README.md 10 | :start-after: 11 | ``` 12 | 13 | ## Indices and tables 14 | 15 | - {ref}`genindex` 16 | - {ref}`modindex` 17 | - {ref}`search` 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | # group updates in a single PR 9 | groups: 10 | actions: 11 | patterns: 12 | - "*" 13 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if ci == 'github' %}.github{% endif %}/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | # group updates in a single PR 9 | groups: 10 | actions: 11 | patterns: 12 | - "*" 13 | -------------------------------------------------------------------------------- /src/pybamm_cookie/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) 2024 The PyBaMM Team. All rights reserved. 3 | 4 | pybamm-cookie: A template for creating battery modeling projects based on PyBaMM 5 | """ 6 | from __future__ import annotations 7 | 8 | from pybamm_cookie.cli import pybamm_cookie_cli 9 | from pybamm_cookie._version import __version__ 10 | 11 | __all__ : list[str] = [ 12 | "__version__", 13 | "pybamm_cookie_cli", 14 | ] 15 | -------------------------------------------------------------------------------- /template/{{ project_name }}/LICENSES-bundled.txt.jinja: -------------------------------------------------------------------------------- 1 | This project and source distributions bundle several libraries that are 2 | compatibly licensed. 3 | 4 | 5 | Name: PyBaMM 6 | Files: - src/{{ project_slug }}/parameters/input/Chen2020.py 7 | - src/{{ project_slug }}/models/input/BasicReservoir.py 8 | - src/{{ project_slug }}/models/input/SPM.py 9 | - src/{{ project_slug }}/entry_point.py 10 | License: BSD-3-Clause 11 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | 5 | version: 2 6 | 7 | build: 8 | os: ubuntu-22.04 9 | tools: 10 | python: "3.11" 11 | jobs: 12 | post_checkout: 13 | - git fetch --unshallow 14 | 15 | sphinx: 16 | configuration: docs/conf.py 17 | 18 | python: 19 | install: 20 | - method: pip 21 | path: . 22 | extra_requirements: 23 | - docs 24 | 25 | formats: 26 | - pdf 27 | - epub 28 | - htmlzip 29 | -------------------------------------------------------------------------------- /template/{{ project_name }}/.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | 5 | version: 2 6 | 7 | build: 8 | os: ubuntu-22.04 9 | tools: 10 | python: "3.11" 11 | jobs: 12 | post_checkout: 13 | - git fetch --unshallow 14 | 15 | sphinx: 16 | configuration: docs/conf.py 17 | 18 | python: 19 | install: 20 | - method: pip 21 | path: . 22 | extra_requirements: 23 | - docs 24 | 25 | formats: 26 | - pdf 27 | - epub 28 | - htmlzip 29 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/__init__.py.jinja: -------------------------------------------------------------------------------- 1 | """ 2 | Copyright (c) {% now 'utc', '%Y' %} {{ full_name }}. All rights reserved. 3 | 4 | {{ project_name }}: {{ project_short_description }} 5 | """ 6 | {%- if mypy %} 7 | from __future__ import annotations 8 | {%- endif %} 9 | 10 | {%- if vcs %} 11 | from importlib.metadata import version 12 | 13 | __version__ = version("{{project_name}}") 14 | 15 | {%- else %} 16 | __version__ = "0.1.0" 17 | {%- endif %} 18 | 19 | import pybamm 20 | from {{project_slug}}.entry_point import Model, parameter_sets, models 21 | {# keep this line here for newline #} 22 | {%- if mypy %} 23 | __all__: list[str] = [ 24 | {%- else %} 25 | __all__ = [ 26 | {%- endif %} 27 | "__version__", 28 | "pybamm", 29 | "parameter_sets", 30 | "Model", 31 | "models", 32 | ] 33 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if license=='MIT' %}LICENSE{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | Copyright {% now 'utc', '%Y' %} {{ full_name }} 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | import importlib.metadata 2 | 3 | project = "pybamm-cookie" 4 | copyright = "2018-2023, The PyBaMM Team" 5 | author = "Agriya Khetarpal" 6 | version = release = importlib.metadata.version("pybamm_cookie") 7 | 8 | extensions = [ 9 | "myst_parser", 10 | "sphinx.ext.autodoc", 11 | "sphinx.ext.intersphinx", 12 | "sphinx.ext.mathjax", 13 | "sphinx.ext.napoleon", 14 | "sphinx_copybutton", 15 | "sphinx_inline_tabs", 16 | "pydata_sphinx_theme", 17 | "nbsphinx", 18 | ] 19 | 20 | source_suffix = [".rst", ".md"] 21 | exclude_patterns = [ 22 | "_build", 23 | "**.ipynb_checkpoints", 24 | "Thumbs.db", 25 | ".DS_Store", 26 | ".env", 27 | ".venv", 28 | ] 29 | 30 | html_theme = "pydata_sphinx_theme" 31 | 32 | myst_enable_extensions = [ 33 | "colon_fence", 34 | ] 35 | 36 | intersphinx_mapping = { 37 | "python": ("https://docs.python.org/3", None), 38 | "numpy": ("https://numpy.org/doc/stable/", None), 39 | "scipy": ("https://docs.scipy.org/doc/scipy/", None), 40 | "matplotlib": ("https://matplotlib.org/stable", None), 41 | "pybamm": ("https://docs.pybamm.org/en/latest/", None), 42 | } 43 | 44 | always_document_param_types = True 45 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Publish to PyPI 2 | on: 3 | release: 4 | types: [published] 5 | 6 | jobs: 7 | build: 8 | name: Build and pybamm-cookie sdist and wheel 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout pybamm-cookie 12 | uses: actions/checkout@v6 13 | 14 | - name: Setup Python 15 | uses: actions/setup-python@v6 16 | 17 | - name: Build package 18 | run: pipx run build 19 | 20 | - name: Upload artifacts 21 | uses: actions/upload-artifact@v6.0.0 22 | with: 23 | name: sdist_and_wheel 24 | path: ./dist/* 25 | if-no-files-found: error 26 | 27 | publish-pypi: 28 | name: Upload package to PyPI 29 | needs: [build] 30 | runs-on: ubuntu-latest 31 | environment: release 32 | permissions: 33 | id-token: write 34 | 35 | steps: 36 | - name: Download all artifacts 37 | uses: actions/download-artifact@v7 38 | with: 39 | path: artifacts 40 | merge-multiple: true 41 | 42 | - name: Publish to PyPI 43 | uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e 44 | with: 45 | packages-dir: artifacts/ 46 | -------------------------------------------------------------------------------- /template/{{ project_name }}/README.md.jinja: -------------------------------------------------------------------------------- 1 | # {{ project_name }} 2 | 3 | [![Actions Status][actions-badge]][actions-link] 4 | [![Documentation Status][rtd-badge]][rtd-link] 5 | 6 | [![PyPI version][pypi-version]][pypi-link] 7 | [![Conda-Forge][conda-badge]][conda-link] 8 | [![PyPI platforms][pypi-platforms]][pypi-link] 9 | 10 | [![GitHub Discussions][github-discussions-badge]][github-discussions-link] 11 | 12 | 13 | 14 | 15 | 16 | [actions-badge]: {{url}}/workflows/CI/badge.svg 17 | [actions-link]: {{url}}/actions 18 | [conda-badge]: https://img.shields.io/conda/vn/conda-forge/{{project_name}} 19 | [conda-link]: https://github.com/conda-forge/{{project_name}}-feedstock 20 | [github-discussions-badge]: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github 21 | [github-discussions-link]: {{url}}/discussions 22 | [pypi-link]: https://pypi.org/project/{{project_name}}/ 23 | [pypi-platforms]: https://img.shields.io/pypi/pyversions/{{project_name}} 24 | [pypi-version]: https://img.shields.io/pypi/v/{{project_name}} 25 | [rtd-badge]: https://readthedocs.org/projects/{{project_name}}/badge/?version=latest 26 | [rtd-link]: https://{{project_name}}.readthedocs.io/en/latest/?badge=latest 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, PyBaMM Team 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if license=='BSD' %}LICENSE{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) {% now 'utc', '%Y' %}, {{ full_name }}. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the vector package developers nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | 4 | ci: 5 | autoupdate_commit_msg: "chore: update pre-commit hooks" 6 | autofix_commit_msg: "style: pre-commit fixes" 7 | 8 | repos: 9 | 10 | # Standard and general-purpose hooks 11 | 12 | - repo: https://github.com/pre-commit/pre-commit-hooks 13 | rev: v6.0.0 14 | hooks: 15 | - id: trailing-whitespace 16 | - id: end-of-file-fixer 17 | - id: check-yaml 18 | files: "^(src/pybamm_cookie|tests$)" 19 | - id: check-added-large-files 20 | - id: mixed-line-ending 21 | 22 | - repo: https://github.com/codespell-project/codespell 23 | rev: v2.4.1 24 | hooks: 25 | - id: codespell 26 | 27 | - repo: local 28 | hooks: 29 | - id: disallow-caps 30 | name: Disallow improper capitalization 31 | language: pygrep 32 | entry: Numpy|Scipy|Cmake|Github|Pybamm 33 | exclude: .pre-commit-config.yaml 34 | 35 | # Python files 36 | 37 | - repo: https://github.com/astral-sh/ruff-pre-commit 38 | rev: v0.14.9 39 | hooks: 40 | - id: ruff 41 | files: "^(src/pybamm_cookie|tests$)" 42 | args: ["--fix", "--show-fixes"] 43 | 44 | # Documentation files 45 | 46 | - repo: https://github.com/asottile/blacken-docs 47 | rev: "1.20.0" 48 | hooks: 49 | - id: blacken-docs 50 | additional_dependencies: [black==23.7.0] 51 | 52 | - repo: https://github.com/pre-commit/pygrep-hooks 53 | rev: "v1.10.0" 54 | hooks: 55 | - id: rst-backticks 56 | - id: rst-directive-colons 57 | - id: rst-inline-touching-normal 58 | 59 | # mypy 60 | 61 | - repo: https://github.com/pre-commit/mirrors-mypy 62 | rev: v1.19.1 63 | hooks: 64 | - id: mypy 65 | files: "^(src/pybamm_cookie|tests$)" 66 | 67 | exclude: 68 | CODE-OF-CONDUCT.md 69 | -------------------------------------------------------------------------------- /template/{{ project_name }}/.pre-commit-config.yaml.jinja: -------------------------------------------------------------------------------- 1 | # Adapted from the Scientific Python style guide 2 | # See https://learn.scientific-python.org/development/guides/style/ 3 | 4 | 5 | ci: 6 | autoupdate_commit_msg: "chore: update pre-commit hooks" 7 | autofix_commit_msg: "style: pre-commit fixes" 8 | 9 | repos: 10 | 11 | - repo: https://github.com/asottile/blacken-docs 12 | rev: "1.15.0" 13 | hooks: 14 | - id: blacken-docs 15 | additional_dependencies: [black==23.7.0] 16 | 17 | - repo: https://github.com/pre-commit/pre-commit-hooks 18 | rev: "v4.4.0" 19 | hooks: 20 | - id: check-added-large-files 21 | - id: check-case-conflict 22 | - id: check-merge-conflict 23 | - id: check-symlinks 24 | - id: check-yaml 25 | - id: debug-statements 26 | - id: end-of-file-fixer 27 | - id: mixed-line-ending 28 | - id: name-tests-test 29 | args: ["--pytest-test-first"] 30 | - id: requirements-txt-fixer 31 | - id: trailing-whitespace 32 | 33 | - repo: https://github.com/pre-commit/pygrep-hooks 34 | rev: "v1.10.0" 35 | hooks: 36 | - id: rst-backticks 37 | - id: rst-directive-colons 38 | - id: rst-inline-touching-normal 39 | 40 | - repo: https://github.com/astral-sh/ruff-pre-commit 41 | rev: "v0.0.280" 42 | hooks: 43 | - id: ruff 44 | args: ["--fix", "--show-fixes"] 45 | 46 | - repo: https://github.com/codespell-project/codespell 47 | rev: "v2.2.5" 48 | hooks: 49 | - id: codespell 50 | 51 | - repo: local 52 | hooks: 53 | - id: disallow-caps 54 | name: Disallow improper capitalization 55 | language: pygrep 56 | entry: PyBind|Numpy|Scipy|Cmake|CCache|Github|Pybamm 57 | exclude: .pre-commit-config.yaml 58 | {# keep this line here for newline #} 59 | {%- if mypy %} 60 | # mypy 61 | 62 | - repo: https://github.com/pre-commit/mirrors-mypy 63 | rev: v1.4.1 64 | hooks: 65 | - id: mypy 66 | files: "^(src/{{ __project_slug }}|tests$)" 67 | {%- endif %} 68 | -------------------------------------------------------------------------------- /tests/template_tests/test_project_generation.py: -------------------------------------------------------------------------------- 1 | import pybamm_cookie as m 2 | import pytest 3 | import os 4 | import subprocess 5 | import shutil 6 | 7 | def test_version() -> None: 8 | assert m.__version__ 9 | 10 | 11 | def test_bake_project(copie): # codespell:ignore copie 12 | """ 13 | Testing the template generation with default values 14 | """ 15 | result = copie.copy() # codespell:ignore copie 16 | 17 | assert result.exit_code == 0, f"Exited with code {result.exit_code}, expected 0" 18 | assert result.exception is None, result.exception 19 | assert result.project_dir.is_dir(), f"Project directory {result.project_dir} not found" 20 | with open(result.project_dir / "pybamm-example-project" / "README.md") as f: 21 | assert f.readline() == "# pybamm-example-project\n", f"{f.readline()} is not the same as # pybamm-example-project\n" 22 | 23 | 24 | def test_template_with_extra_answers(copie): # codespell:ignore copie 25 | """ 26 | Testing the template generation with custom template and checking if the projects exists in the tmp_path 27 | """ 28 | extra_context = { 29 | "project_name": "test-bake-project", 30 | "email": "pybamm@pybamm.org", 31 | "project_slug": "pybamm_cookie", 32 | "project_short_description": "This is an example pybamm-cookie template", 33 | "url": "pybamm.org", 34 | } 35 | result = copie.copy(extra_answers=extra_context) # codespell:ignore copie 36 | 37 | assert result.exit_code == 0, f"Exited with code {result.exit_code}, expected 0" 38 | assert result.exception is None, result.exception 39 | assert result.project_dir.is_dir(), f"Project directory {result.project_dir} not found" 40 | with open(result.project_dir / extra_context["project_name"] / "README.md") as f: 41 | assert f.readline() == f"# {extra_context['project_name']}\n", f"{f.readline()} is not the same as {extra_context['project_name']}\n" 42 | 43 | def test_cli(): 44 | """ 45 | Testing if the CLI works and returns a successful exit code on execution 46 | """ 47 | os.mkdir("testcli") 48 | return_code = subprocess.run(["pybamm-cookie", "--defaults"], cwd = "./testcli") 49 | shutil.rmtree("testcli") 50 | assert return_code 51 | -------------------------------------------------------------------------------- /src/pybamm_cookie/cli.py: -------------------------------------------------------------------------------- 1 | import copier 2 | import argparse 3 | from pathlib import Path 4 | from colorama import Fore 5 | import os 6 | 7 | project_root = Path(__file__).resolve().parent.parent 8 | TEMPLATE = str(project_root) 9 | 10 | def pybamm_cookie_cli(): 11 | """ 12 | Command Line Interface (CLI) for generating PyBaMM based projects using copier. 13 | 14 | Parameters 15 | ---------- 16 | --path: pathlib.Path 17 | 18 | Examples 19 | ------- 20 | $ pybamm-cookie 21 | Generates a project in the current working directory of the terminal. 22 | $ pybamm-cookie --path /myproject 23 | Generates a project in the `myproject` directory. 24 | """ 25 | try: 26 | parser = argparse.ArgumentParser(description = "A copier template generator for PyBaMM based projects") 27 | parser.add_argument( 28 | "--path", type = str, 29 | required = False, 30 | default = os.getcwd(), 31 | help = "The destination path for project generation. The default is the current working directory" 32 | ) 33 | 34 | from pybamm_cookie import __version__ as version 35 | parser.add_argument( 36 | '--version', 37 | action='version', 38 | version=f'pybamm-cookie CLI Version - {version}' 39 | ) 40 | 41 | parser.add_argument( 42 | "--defaults", 43 | action="store_true", 44 | help="Whether to use default options for generating the template" 45 | ) 46 | args = parser.parse_args() 47 | destination_path = Path(args.path) 48 | 49 | with copier.Worker(src_path = TEMPLATE, dst_path = destination_path, unsafe = True, defaults = args.defaults) as worker: 50 | worker.run_copy() 51 | 52 | except KeyboardInterrupt: 53 | print(Fore.RED + "Execution stopped by the user" + Fore.RESET) 54 | except Exception as error: 55 | print(Fore.RED + "Error caused by an exception: " + Fore.RESET, error) 56 | print(Fore.CYAN + "If you are unsure what the error is, feel free to open an issue at" + Fore.YELLOW +" - https://github.com/pybamm-team/pybamm-cookie/issues" + Fore.RESET) 57 | 58 | if __name__ == '__main__': 59 | 60 | pybamm_cookie_cli() 61 | -------------------------------------------------------------------------------- /noxfile.py: -------------------------------------------------------------------------------- 1 | import nox 2 | from pathlib import Path 3 | import os 4 | 5 | # Options to modify nox behaviour 6 | nox.options.default_venv_backend = "uv|virtualenv" 7 | nox.options.reuse_existing_virtualenvs = True 8 | 9 | VENV_DIR = Path("./venv").resolve() 10 | 11 | @nox.session(name="docs") 12 | def build_docs(session: nox.Session) -> None: 13 | """Build the documentation and load it in a browser tab, rebuilding on changes.""" 14 | session.install("-e", ".[docs]") 15 | with session.chdir("docs/"): 16 | # For local development 17 | if session.interactive: 18 | session.run( 19 | "sphinx-autobuild", 20 | "-j", 21 | "auto", 22 | "--open-browser", 23 | "-qT", 24 | ".", 25 | "build/html/", 26 | ) 27 | # For CI testing if documentation builds 28 | else: 29 | session.run( 30 | "sphinx-build", 31 | "-b", 32 | "html", 33 | "-W", 34 | "--keep-going", 35 | ".", 36 | "build/html/", 37 | ) 38 | def install_and_run_tests(session, test_dir): 39 | """Install dependencies and run tests in the specified directory.""" 40 | session.install("setuptools", silent=False) 41 | session.install("-e", ".[dev]", silent=False) 42 | session.run("pytest", test_dir) 43 | 44 | @nox.session(name="template-tests") 45 | def run_template_generation(session): 46 | """Run tests for the template generation.""" 47 | install_and_run_tests(session, "tests/template_tests") 48 | 49 | @nox.session(name="coverage") 50 | def run_coverage(session): 51 | """Run the coverage tests and generate an XML report.""" 52 | session.install("setuptools", silent=False) 53 | session.install("coverage", silent=False) 54 | session.install("-e", ".[dev]", silent=False) 55 | session.run("pytest", "--cov=src/pybamm_cookie", "--cov-report=xml", "tests/") 56 | 57 | @nox.session(name="dev") 58 | def set_dev(session): 59 | """Install pybamm-cookie in editable mode""" 60 | session.install("virtualenv") 61 | session.run("virtualenv", os.fsdecode(VENV_DIR), silent=True) 62 | python = os.fsdecode(VENV_DIR.joinpath("bin/python")) 63 | session.run(python, "-m", "pip", "install", "-e", ".[dev]") 64 | -------------------------------------------------------------------------------- /template/{{ project_name }}/tests/generated_project_tests/test_entry_points.py.jinja: -------------------------------------------------------------------------------- 1 | import pytest 2 | import {{ project_slug }} 3 | import importlib.util 4 | import sys 5 | from pathlib import Path 6 | 7 | 8 | def test_parameter_sets_entry_points(): 9 | """Test if the parameter_sets via entry points are loaded correctly.""" 10 | 11 | entry_points = list({{ project_slug }}.parameter_sets).sort() 12 | parameter_sets = Path("src/{{ project_slug }}/parameters/input/").glob("*.py") 13 | # Making a list of parameter sets in the parameters/input directory 14 | parameter_sets = [x.stem for x in parameter_sets].sort() 15 | 16 | assert parameter_sets == entry_points, "Entry points missing either in pyproject.toml or in the input directory" 17 | 18 | 19 | def test_parameter_sets_entry_point_load(): 20 | """Testing if the values get loaded via parameter entry points and are equal when loaded through entry points""" 21 | # Loading parameter_sets through entry points 22 | parameters = {{ project_slug }}.parameter_sets['Chen2020'] 23 | # Loading parameter sets through the source file by dynamically loading Chen2020.py as a module 24 | spec = importlib.util.spec_from_file_location("Chen2020mod", "src/{{ project_slug }}/parameters/input/Chen2020.py") 25 | chen_module = importlib.util.module_from_spec(spec) 26 | sys.modules["Chen2020mod"] = chen_module 27 | spec.loader.exec_module(chen_module) 28 | parameters_from_file = chen_module.get_parameter_values() 29 | assert parameters.keys() == parameters_from_file.keys(), f"The keys in the module and local input file are not the same, expected {parameters.keys}, got {parameters_from_file.keys()}" 30 | 31 | def test_model_entry_points(): 32 | """Test if the models via entry points are loaded correctly.""" 33 | 34 | entry_points = list({{ project_slug }}.models).sort() 35 | models = Path("src/{{ project_slug }}/models/input/").glob("*.py") 36 | # Making a list Parameter sets in the parameters/input directory 37 | models = [x.stem for x in models].sort() 38 | 39 | assert models == entry_points, "Entry points missing either in pyproject.toml or in the input directory" 40 | 41 | 42 | def test_model_entry_point_load(): 43 | """Testing if the model gets initialised and returned.""" 44 | # Loading parameter_sets through entry points 45 | model_instance = {{ project_slug }}.Model("SPM") 46 | assert model_instance is not None 47 | -------------------------------------------------------------------------------- /template/{{ project_name }}/.gitignore: -------------------------------------------------------------------------------- 1 | # Adapted from the Scientific Python style guide 2 | # See https://learn.scientific-python.org/development/guides/style/ 3 | 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | cover/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Sphinx documentation 63 | docs/_build/ 64 | 65 | # PyBuilder 66 | .pybuilder/ 67 | target/ 68 | 69 | # Jupyter Notebook 70 | .ipynb_checkpoints 71 | 72 | # IPython 73 | profile_default/ 74 | ipython_config.py 75 | 76 | # pyenv 77 | # For a library or package, you might want to ignore these files since the code is 78 | # intended to run in multiple environments; otherwise, check them in: 79 | # .python-version 80 | 81 | # pipenv 82 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 83 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 84 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 85 | # install all needed dependencies. 86 | #Pipfile.lock 87 | 88 | # Environments 89 | .env 90 | .venv 91 | env/ 92 | venv/ 93 | ENV/ 94 | env.bak/ 95 | venv.bak/ 96 | 97 | # Spyder project settings 98 | .spyderproject 99 | .spyproject 100 | 101 | # Rope project settings 102 | .ropeproject 103 | 104 | # setuptools_scm 105 | src/*/_version.py 106 | 107 | # ruff 108 | .ruff_cache/ 109 | 110 | # OS specific stuff 111 | .DS_Store 112 | .DS_Store? 113 | ._* 114 | .Spotlight-V100 115 | .Trashes 116 | ehthumbs.db 117 | Thumbs.db 118 | 119 | # Common editor files 120 | *~ 121 | *.swp 122 | 123 | # hatch-vcs 124 | */_version.py 125 | 126 | # mypy 127 | .mypy_cache 128 | .dmypy.json 129 | dmypy.json 130 | -------------------------------------------------------------------------------- /template/{{ project_name }}/noxfile.py.jinja: -------------------------------------------------------------------------------- 1 | import nox 2 | from pathlib import Path 3 | import os 4 | 5 | # Options to modify nox behaviour 6 | nox.options.default_venv_backend = "uv|virtualenv" 7 | nox.options.reuse_existing_virtualenvs = True 8 | 9 | VENV_DIR = Path("./venv").resolve() 10 | 11 | @nox.session(name="docs") 12 | def build_docs(session: nox.Session) -> None: 13 | """Build the documentation and load it in a browser tab, rebuilding on changes.""" 14 | session.install("setuptools") 15 | session.install("-e", ".[docs]") 16 | with session.chdir("docs/"): 17 | # For local development 18 | if session.interactive: 19 | session.run( 20 | "sphinx-autobuild", 21 | "-j", 22 | "auto", 23 | "--open-browser", 24 | "-qT", 25 | ".", 26 | "build/html/", 27 | ) 28 | # For CI testing if documentation builds 29 | else: 30 | session.run( 31 | "sphinx-build", 32 | "-b", 33 | "html", 34 | "-W", 35 | "--keep-going", 36 | ".", 37 | "build/html/", 38 | ) 39 | 40 | def install_and_run_tests(session, test_dir): 41 | """Install dependencies and run tests in the specified directory.""" 42 | session.install("setuptools", silent=False) 43 | session.install("-e", ".[dev]", silent=False) 44 | session.run("pytest", test_dir) 45 | 46 | @nox.session(name="generated-project-tests") 47 | def run_generated_project_tests(session): 48 | """Run the tests for testing units inside generated project""" 49 | install_and_run_tests(session, "tests/generated_project_tests") 50 | 51 | @nox.session(name="user-tests") 52 | def run_user_tests(session): 53 | """Run user written tests""" 54 | install_and_run_tests(session, "tests/user_tests") 55 | 56 | @nox.session(name="coverage") 57 | def run_coverage(session): 58 | """Run the coverage tests and generate an XML report.""" 59 | session.install("setuptools", silent=False) 60 | session.install("coverage", silent=False) 61 | session.install("-e", ".[dev]", silent=False) 62 | session.run("pytest", "--cov=src/{{project_slug}}", "--cov-report=xml", "tests/") 63 | 64 | @nox.session(name="dev") 65 | def set_dev(session): 66 | """Install pybamm-cookie in editable mode""" 67 | session.install("virtualenv") 68 | session.run("virtualenv", os.fsdecode(VENV_DIR), silent=True) 69 | python = os.fsdecode(VENV_DIR.joinpath("bin/python")) 70 | session.run(python, "-m", "pip", "install", "-e", ".[dev]") 71 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if ci == 'github' %}.github{% endif %}/workflows/test_on_push.yml: -------------------------------------------------------------------------------- 1 | name: Project Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | style: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Setup Python 16 | uses: actions/setup-python@v5 17 | with: 18 | python-version: 3.12 19 | 20 | - name: Check style 21 | run: | 22 | python -m pip install pre-commit 23 | pre-commit run -a 24 | 25 | test_project: 26 | needs: style 27 | runs-on: ${{ matrix.os }} 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | os: [ubuntu-latest, macos-13, macos-14, windows-latest] 32 | python-version: ["3.9", "3.10", "3.11", "3.12"] 33 | name: 34 | Template Generation/Project Tests (${{ matrix.os }} / Python ${{ matrix.python-version }}) 35 | steps: 36 | - name: Checkout pybamm-cookie 37 | uses: actions/checkout@v4 38 | with: 39 | fetch-depth: 0 40 | 41 | - name: Set up Python ${{ matrix.python-version }} 42 | id: setup-python 43 | uses: actions/setup-python@v5 44 | with: 45 | python-version: ${{ matrix.python-version }} 46 | 47 | - name: Set up uv 48 | uses: yezz123/setup-uv@v4 49 | with: 50 | uv-venv: ".venv" 51 | 52 | - name: Install nox 53 | run: uv pip install nox[uv] 54 | 55 | - name: Test project units 56 | run: nox -s generated-project-tests 57 | 58 | - name: Test user tests 59 | run: nox -s user-tests 60 | 61 | - name: Run coverage tests 62 | if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' 63 | run: nox -s coverage 64 | 65 | - name: Upload coverage report 66 | if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' 67 | uses: codecov/codecov-action@v4.5.0 68 | with: 69 | token: ${{ secrets.CODECOV_TOKEN }} 70 | 71 | run_doctests: 72 | needs: style 73 | runs-on: ubuntu-latest 74 | name: Doctests (ubuntu-latest / Python 3.12) 75 | 76 | steps: 77 | - name: Check out pybamm-cookie repository 78 | uses: actions/checkout@v4 79 | 80 | - name: Set up Python 81 | uses: actions/setup-python@v5 82 | with: 83 | python-version: 3.12 84 | 85 | - name: Set up uv 86 | uses: yezz123/setup-uv@v4 87 | with: 88 | uv-venv: ".venv" 89 | 90 | - name: Install nox 91 | run: uv pip install nox[uv] 92 | 93 | - name: Check if the documentation can be built 94 | run: nox -s docs 95 | -------------------------------------------------------------------------------- /copier.yml: -------------------------------------------------------------------------------- 1 | project_name: 2 | type: str 3 | default: "pybamm-example-project" 4 | help: "The name of your project" 5 | 6 | project_slug: 7 | type: str 8 | help: The name of the directory containing the Python files for your project. This should be in `snake_case`, and this is what you will import it with, such as `import pybamm_example_project`. 9 | default: "{{ project_name|lower|replace('-', '_')|replace(' ', '_') }}" 10 | validator: | 11 | {% if ('-' in project_slug or ' ' in project_slug) %} 12 | The name of the directory should not contain spaces or hyphens 13 | {% endif %} 14 | 15 | platform: 16 | type: str 17 | choices: 18 | - github 19 | - gitlab 20 | default: github 21 | help: "The platform you are using to host your project" 22 | 23 | org: 24 | type: str 25 | default: "pybamm-team" 26 | help: "The name of your organisation (or username, if you are not part of an organisation)" 27 | 28 | url: 29 | type: str 30 | default: "https://{{ platform }}.com/{{ org }}/{{ project_name }}" 31 | help: "The origin URL to your code repository" 32 | 33 | branch: 34 | type: str 35 | default: "main" 36 | help: "The default branch of your repository" 37 | 38 | full_name: 39 | type: str 40 | default: "John Doe" 41 | help: "Your name on your hosting platform (will be used later as your committer name)" 42 | 43 | email: 44 | type: str 45 | default: "john@doe.com" 46 | help: "Your email for your hosting platform (will be used later to configure Git)" 47 | 48 | project_short_description: 49 | type: str 50 | default: "A battery modelling project that uses the PyBaMM framework" 51 | help: "A short description of your project" 52 | 53 | license: 54 | type: str 55 | choices: 56 | - BSD-3-Clause 57 | - Apache 58 | - MIT 59 | default: BSD-3-Clause 60 | help: "Select a license" 61 | 62 | backend: 63 | type: str 64 | choices: 65 | - "hatch" 66 | - "setuptools" 67 | default: "hatch" 68 | help: "Choose a build backend. hatch (hatchling) is recommended for pure Python projects and for beginners, while setuptools offers more classic yet modern configuration choices" 69 | 70 | vcs: 71 | type: bool 72 | default: false 73 | help: "Let the build backend get the version from your version control system (Git/Mercurial/SVN) using the hatch-vcs (for hatchling) or the setuptools-scm (for setuptools) plugins?" 74 | 75 | mypy: 76 | type: bool 77 | default: false 78 | help: "Use the mypy type checker" 79 | 80 | 81 | _copy_without_render: 82 | type: list 83 | default: ["*.yml"] 84 | 85 | _jinja_extensions: 86 | - jinja2_time.TimeExtension 87 | 88 | _subdirectory: template 89 | 90 | _exclude: 91 | - copier.yml 92 | 93 | _tasks: 94 | - command: git init -b {{branch}} 95 | working_directory: "{{project_name}}" 96 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Scrapy stuff: 59 | .scrapy 60 | 61 | # Sphinx documentation 62 | docs/_build/ 63 | 64 | # PyBuilder 65 | .pybuilder/ 66 | target/ 67 | 68 | # Jupyter Notebook 69 | .ipynb_checkpoints 70 | 71 | # IPython 72 | profile_default/ 73 | ipython_config.py 74 | 75 | # pyenv 76 | # For a library or package, you might want to ignore these files since the code is 77 | # intended to run in multiple environments; otherwise, check them in: 78 | # .python-version 79 | 80 | # pipenv 81 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 82 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 83 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 84 | # install all needed dependencies. 85 | #Pipfile.lock 86 | 87 | # Environments 88 | .env 89 | .venv 90 | env/ 91 | venv/ 92 | ENV/ 93 | env.bak/ 94 | venv.bak/ 95 | 96 | # Spyder project settings 97 | .spyderproject 98 | .spyproject 99 | 100 | # Rope project settings 101 | .ropeproject 102 | 103 | # mkdocs documentation 104 | /site 105 | 106 | # mypy 107 | .mypy_cache/ 108 | .dmypy.json 109 | dmypy.json 110 | 111 | # Pyre type checker 112 | .pyre/ 113 | 114 | # pytype static type analyzer 115 | .pytype/ 116 | 117 | # Cython debug symbols 118 | cython_debug/ 119 | 120 | # PyCharm 121 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 122 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 123 | # and can be added to the global gitignore or merged into this file. For a more nuclear 124 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 125 | #.idea/ 126 | 127 | # Code editor files and folders 128 | .vscode/ 129 | 130 | # hatch-vcs 131 | src/pybamm_cookie/_version.py 132 | 133 | # ruff 134 | .ruff_cache/ 135 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling", "hatch-vcs"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "pybamm-cookie" 7 | authors = [ 8 | { name = "Agriya Khetarpal", email = "agriyakhetarpal@outlook.com" }, 9 | { name = "Santhosh Sundaram", email = "santhoshsundaram9650@gmail.com" }, 10 | ] 11 | maintainers = [ 12 | { name = "PyBaMM Team", email = "pybamm@pybamm.org" }, 13 | ] 14 | description = "A template for creating battery modeling projects based on PyBaMM" 15 | readme = "README.md" 16 | requires-python = ">=3.8" # PyBaMM supports 3.8 and above 17 | classifiers = [ 18 | "Development Status :: 1 - Planning", 19 | "Intended Audience :: Science/Research", 20 | "Intended Audience :: Developers", 21 | "License :: OSI Approved :: BSD License", 22 | "Operating System :: OS Independent", 23 | "Programming Language :: Python", 24 | "Programming Language :: Python :: 3", 25 | "Programming Language :: Python :: 3 :: Only", 26 | "Programming Language :: Python :: 3.8", 27 | "Programming Language :: Python :: 3.9", 28 | "Programming Language :: Python :: 3.10", 29 | "Programming Language :: Python :: 3.11", # PyBaMM supports >=3.8,<3.12 30 | "Topic :: Scientific/Engineering", 31 | "Typing :: Typed", 32 | ] 33 | dynamic = ["version"] 34 | dependencies = ["copier", "jinja2-time", "colorama"] 35 | 36 | [project.optional-dependencies] 37 | dev = [ 38 | "pytest >=6", 39 | "pytest-cov >=3", 40 | "nox[uv]", 41 | "pre-commit", 42 | "pytest-copie", 43 | ] 44 | docs = [ 45 | "sphinx", 46 | "pydata_sphinx_theme", 47 | "sphinx_design", 48 | "sphinx-copybutton", 49 | "myst-parser", 50 | "sphinx-inline-tabs", 51 | "sphinxcontrib-bibtex", 52 | "sphinx-autobuild", 53 | "sphinx-last-updated-by-git", 54 | "nbsphinx", 55 | "ipython", 56 | "sphinx-gallery", 57 | ] 58 | 59 | [project.scripts] 60 | pybamm-cookie = "pybamm_cookie.cli:pybamm_cookie_cli" 61 | 62 | [project.entry-points."pipx.run"] 63 | pybamm-cookie = "pybamm_cookie.cli:pybamm_cookie_cli" 64 | 65 | [project.urls] 66 | Homepage = "https://github.com/pybamm-team/pybamm-cookie" 67 | "Bug Tracker" = "https://github.com/pybamm-team/pybamm-cookie/issues" 68 | Discussions = "https://github.com/pybamm-team/pybamm-cookie/discussions" 69 | Changelog = "https://github.com/pybamm-team/pybamm-cookie/releases" 70 | 71 | [tool.hatch] 72 | version.source = "vcs" 73 | build.hooks.vcs.version-file = "src/pybamm_cookie/_version.py" 74 | envs.default.dependencies = [ 75 | "pybamm", 76 | ] 77 | 78 | [tool.hatch.build.targets.wheel] 79 | only-include = ["src/pybamm_cookie", "/template", "copier.yml", "LICENSE", "LICENSES-bundled.txt"] 80 | sources = ["src"] 81 | 82 | [tool.mypy] 83 | packages = [ 84 | "src/pybamm_cookie", 85 | "tests" 86 | ] 87 | python_version = "3.11" 88 | strict = false 89 | warn_return_any = false 90 | show_error_codes = true 91 | enable_error_code = [ 92 | "ignore-without-code", 93 | "truthy-bool", 94 | "redundant-expr", 95 | ] 96 | disallow_untyped_defs = false 97 | disallow_untyped_calls = false 98 | ignore_missing_imports = true 99 | allow_redefinition = true 100 | disable_error_code = ["call-overload", "operator"] 101 | 102 | [tool.coverage] 103 | run.source = ["pybamm_cookie"] 104 | port.exclude_lines = [ 105 | 'pragma: no cover', 106 | ] 107 | 108 | [tool.ruff] 109 | extend-include = ["*.ipynb"] 110 | extend-exclude = ["__init__.py"] 111 | src = ["src"] 112 | exclude = [] 113 | isort.required-imports = ["from __future__ import annotations"] 114 | flake8-unused-arguments.ignore-variadic-names = true 115 | 116 | 117 | [tool.ruff.lint] 118 | extend-select = [ 119 | "B", # flake8-bugbear 120 | "RUF", # Ruff-specific 121 | "UP", # pyupgrade 122 | "YTT", # flake8-2020 123 | "TID252", # relative-imports 124 | ] 125 | ignore = [ 126 | "E741", # Ambiguous variable name 127 | "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` 128 | "SIM108", # Use ternary operator 129 | "ARG001", # Unused function argument: 130 | "ARG002", # Unused method arguments 131 | "PLR2004", # Magic value used in comparison 132 | "PLR0915", # Too many statements 133 | "PLR0913", # Too many arguments 134 | "PLR0912", # Too many branches 135 | "RET504", # Unnecessary assignment 136 | "RET505", # Unnecessary `else` 137 | "RET506", # Unnecessary `elif` 138 | "B018", # Found useless expression 139 | "RUF002", # Docstring contains ambiguous 140 | "UP007", # For pyupgrade 141 | ] 142 | 143 | [tool.ruff.lint.per-file-ignores] 144 | "tests/*" = ["T20"] 145 | "docs/*" = ["T20"] 146 | -------------------------------------------------------------------------------- /template/{{ project_name }}/pyproject.toml.jinja: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | {%- if backend == "hatch" %} 4 | "hatchling", 5 | {%- elif backend == "setuptools" %} 6 | "setuptools", 7 | {%- endif %} 8 | {%- if backend == "hatch" and vcs == true %} 9 | "hatch-vcs", 10 | {%- elif backend == "setuptools" and vcs == true %} 11 | "setuptools_scm[toml]>=8.1.0", 12 | {%- endif %} 13 | ] 14 | {%- if backend == "hatch" %} 15 | build-backend = "hatchling.build" 16 | {%- elif backend == "setuptools" %} 17 | build-backend = "setuptools.build_meta" 18 | {%- endif %} 19 | 20 | [project] 21 | name = "{{ project_name }}" 22 | {%- if backend == "setuptools" and vcs == false %} 23 | version = "0.0.1" 24 | {%- elif backend == "setuptools" and vcs == true %} 25 | dynamic = ["version"] 26 | {%- endif %} 27 | authors = [ 28 | { name = "{{ full_name }}", email = "{{ email }}" }, 29 | ] 30 | {%- if org | lower == "pybamm-team" %} 31 | maintainers = [ 32 | { name = "The PyBaMM Team", email = "pybamm@pybamm.org" }, 33 | ] 34 | {%- endif %} 35 | description = "{{ project_short_description }}" 36 | readme = "README.md" 37 | requires-python = ">=3.8" 38 | classifiers = [ 39 | "Development Status :: 1 - Planning", 40 | "Intended Audience :: Science/Research", 41 | "Intended Audience :: Developers", 42 | {%- if license == "BSD-3-Clause" %} 43 | "License :: OSI Approved :: BSD License", 44 | {%- elif license == "Apache" %} 45 | "License :: OSI Approved :: Apache Software License", 46 | {%- elif license == "MIT" %} 47 | "License :: OSI Approved :: MIT License", 48 | {%- endif %} 49 | "Operating System :: OS Independent", 50 | "Programming Language :: Python", 51 | "Programming Language :: Python :: 3", 52 | "Programming Language :: Python :: 3 :: Only", 53 | "Programming Language :: Python :: 3.8", 54 | "Programming Language :: Python :: 3.9", 55 | "Programming Language :: Python :: 3.10", 56 | "Programming Language :: Python :: 3.11", 57 | "Topic :: Scientific/Engineering", 58 | {%- if mypy %} 59 | "Typing :: Typed", 60 | {%- endif %} 61 | ] 62 | {%- if backend == "hatch" %} 63 | dynamic = ["version"] 64 | {%- endif %} 65 | dependencies = ["pybamm",] 66 | 67 | [project.optional-dependencies] 68 | dev = [ 69 | "pytest >=6", 70 | "pytest-cov >=3", 71 | "nox[uv]", 72 | "pre-commit", 73 | ] 74 | docs = [ 75 | "sphinx", 76 | "pydata_sphinx_theme", 77 | "sphinx_design", 78 | "sphinx-copybutton", 79 | "myst-parser", 80 | "sphinx-inline-tabs", 81 | "sphinxcontrib-bibtex", 82 | "sphinx-autobuild", 83 | "sphinx-last-updated-by-git", 84 | "nbsphinx", 85 | "ipython", 86 | "sphinx-gallery", 87 | ] 88 | 89 | [project.urls] 90 | Homepage = "{{ url }}" 91 | "Bug Tracker" = "{{ url }}/issues" 92 | Discussions = "{{ url }}/discussions" 93 | Changelog = "{{ url }}/releases" 94 | 95 | [project.entry-points."parameter_sets"] 96 | Chen2020 = "{{ project_slug }}.parameters.input.Chen2020:get_parameter_values" 97 | 98 | [project.entry-points."models"] 99 | SPM = "{{ project_slug }}.models.input.SPM:SPM" 100 | BasicReservoir = "{{ project_slug }}.models.input.BasicReservoir:BasicReservoir" 101 | {# keep this line here for newline #} 102 | {%- if backend == "hatch" %} 103 | [tool.hatch] 104 | {%- if backend == "hatch" and vcs == true %} 105 | version.source = "vcs" 106 | build.hooks.vcs.version-file = "src/{{ project_slug }}/_version.py" 107 | {%- endif %} 108 | envs.default.dependencies = [ 109 | "pybamm", 110 | ] 111 | {%- endif %} 112 | 113 | {%- if backend == "hatch" and vcs == false %} 114 | [tool.hatch.version] 115 | path = "src/{{ project_slug }}/__init__.py" 116 | 117 | [tool.hatch.build.targets.wheel] 118 | packages = ["src/{{ project_slug }}"] 119 | {%- endif %} 120 | {# keep this line here for newline #} 121 | {%- if backend == "setuptools" and vcs == true %} 122 | [tool.setuptools_scm] 123 | version_file = "src/{{ project_slug }}/_version.py" 124 | {%- endif %} 125 | 126 | {%- if mypy %} 127 | [tool.mypy] 128 | python_version = "3.11" 129 | strict = false 130 | warn_return_any = false 131 | show_error_codes = true 132 | enable_error_code = [ 133 | "ignore-without-code", 134 | "truthy-bool", 135 | "redundant-expr", 136 | ] 137 | disallow_untyped_defs = false 138 | disallow_untyped_calls = false 139 | ignore_missing_imports = true 140 | allow_redefinition = true 141 | disable_error_code = ["call-overload", "operator"] 142 | {%- endif %} 143 | 144 | [tool.coverage] 145 | run.source = ["{{ project_slug }}"] 146 | port.exclude_lines = [ 147 | 'pragma: no cover', 148 | ] 149 | 150 | [tool.ruff] 151 | select = [ 152 | "E", "F", "W", # flake8 153 | "B", # flake8-bugbear 154 | "I", # isort 155 | #"ARG", # flake8-unused-arguments 156 | "C4", # flake8-comprehensions 157 | "EM", # flake8-errmsg 158 | "ICN", # flake8-import-conventions 159 | "ISC", # flake8-implicit-str-concat 160 | "G", # flake8-logging-format 161 | "PGH", # pygrep-hooks 162 | "PIE", # flake8-pie 163 | "PL", # pylint 164 | "PT", # flake8-pytest-style 165 | "PTH", # flake8-use-pathlib 166 | #"RET", # flake8-return 167 | "RUF", # Ruff-specific 168 | "SIM", # flake8-simplify 169 | "T20", # flake8-print 170 | "UP", # pyupgrade 171 | "YTT", # flake8-2020 172 | "EXE", # flake8-executable 173 | "NPY", # NumPy specific rules 174 | "PD", # pandas-vet 175 | ] 176 | src = ["src"] 177 | unfixable = [ 178 | "T20", # Removes print statements 179 | "F841", # Removes unused variables 180 | ] 181 | ignore = [ 182 | "E741", # Ambiguous variable name 183 | "E501", # Line too long 184 | "PLR2004", # Magic value used in comparison 185 | ] 186 | line-length = 100 187 | exclude = [] 188 | flake8-unused-arguments.ignore-variadic-names = true 189 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE-OF-CONDUCT.md) 2 | 3 | 4 | # `pybamm-cookie` Code of Conduct 5 | 6 | ## Our Pledge 7 | 8 | We as members, contributors, and leaders pledge to make participation in our 9 | community a harassment-free experience for everyone, regardless of age, body 10 | size, visible or invisible disability, ethnicity, sex characteristics, gender 11 | identity and expression, level of experience, education, socio-economic status, 12 | nationality, personal appearance, race, caste, color, religion, or sexual 13 | identity and orientation. 14 | 15 | We pledge to act and interact in ways that contribute to an open, welcoming, 16 | diverse, inclusive, and healthy community. 17 | 18 | ## Our Standards 19 | 20 | Examples of behavior that contributes to a positive environment for our 21 | community include: 22 | 23 | * Demonstrating empathy and kindness toward other people 24 | * Being respectful of differing opinions, viewpoints, and experiences 25 | * Giving and gracefully accepting constructive feedback 26 | * Accepting responsibility and apologizing to those affected by our mistakes, 27 | and learning from the experience 28 | * Focusing on what is best not just for us as individuals, but for the overall 29 | community 30 | 31 | Examples of unacceptable behavior include: 32 | 33 | * The use of sexualized language or imagery, and sexual attention or advances of 34 | any kind 35 | * Trolling, insulting or derogatory comments, and personal or political attacks 36 | * Public or private harassment 37 | * Publishing others' private information, such as a physical or email address, 38 | without their explicit permission 39 | * Other conduct which could reasonably be considered inappropriate in a 40 | professional setting 41 | 42 | ## Enforcement Responsibilities 43 | 44 | Community leaders are responsible for clarifying and enforcing our standards of 45 | acceptable behavior and will take appropriate and fair corrective action in 46 | response to any behavior that they deem inappropriate, threatening, offensive, 47 | or harmful. 48 | 49 | Community leaders have the right and responsibility to remove, edit, or reject 50 | comments, commits, code, wiki edits, issues, and other contributions that are 51 | not aligned to this Code of Conduct, and will communicate reasons for moderation 52 | decisions when appropriate. 53 | 54 | ## Scope 55 | 56 | This Code of Conduct applies within all community spaces, and also applies when 57 | an individual is officially representing the community in public spaces. 58 | Examples of representing our community include using an official email address, 59 | posting via an official social media account, or acting as an appointed 60 | representative at an online or offline event. 61 | 62 | ## Enforcement 63 | 64 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 65 | reported to the community leaders responsible for enforcement at 66 | [pybamm@pybamm.org](mailto:pybamm@pybamm.org). 67 | All complaints will be reviewed and investigated promptly and fairly. 68 | 69 | All community leaders are obligated to respect the privacy and security of the 70 | reporter of any incident. 71 | 72 | ## Enforcement Guidelines 73 | 74 | Community leaders will follow these Community Impact Guidelines in determining 75 | the consequences for any action they deem in violation of this Code of Conduct: 76 | 77 | ### 1. Correction 78 | 79 | **Community Impact**: Use of inappropriate language or other behavior deemed 80 | unprofessional or unwelcome in the community. 81 | 82 | **Consequence**: A private, written warning from community leaders, providing 83 | clarity around the nature of the violation and an explanation of why the 84 | behavior was inappropriate. A public apology may be requested. 85 | 86 | ### 2. Warning 87 | 88 | **Community Impact**: A violation through a single incident or series of 89 | actions. 90 | 91 | **Consequence**: A warning with consequences for continued behavior. No 92 | interaction with the people involved, including unsolicited interaction with 93 | those enforcing the Code of Conduct, for a specified period of time. This 94 | includes avoiding interactions in community spaces as well as external channels 95 | like social media. Violating these terms may lead to a temporary or permanent 96 | ban. 97 | 98 | ### 3. Temporary Ban 99 | 100 | **Community Impact**: A serious violation of community standards, including 101 | sustained inappropriate behavior. 102 | 103 | **Consequence**: A temporary ban from any sort of interaction or public 104 | communication with the community for a specified period of time. No public or 105 | private interaction with the people involved, including unsolicited interaction 106 | with those enforcing the Code of Conduct, is allowed during this period. 107 | Violating these terms may lead to a permanent ban. 108 | 109 | ### 4. Permanent Ban 110 | 111 | **Community Impact**: Demonstrating a pattern of violation of community 112 | standards, including sustained inappropriate behavior, harassment of an 113 | individual, or aggression toward or disparagement of classes of individuals. 114 | 115 | **Consequence**: A permanent ban from any sort of public interaction within the 116 | community. 117 | 118 | ## Attribution 119 | 120 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 121 | version 2.1, available at 122 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 123 | 124 | Community Impact Guidelines were inspired by 125 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 126 | 127 | For answers to common questions about this code of conduct, see the FAQ at 128 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 129 | [https://www.contributor-covenant.org/translations][translations]. 130 | 131 | [homepage]: https://www.contributor-covenant.org 132 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 133 | [Mozilla CoC]: https://github.com/mozilla/diversity 134 | [FAQ]: https://www.contributor-covenant.org/faq 135 | [translations]: https://www.contributor-covenant.org/translations 136 | -------------------------------------------------------------------------------- /.github/workflows/test_on_push.yml: -------------------------------------------------------------------------------- 1 | name: Test template and generated project 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | 10 | concurrency: 11 | # Skip intermediate builds: always. 12 | # Cancel intermediate builds: only if it is a pull request build. 13 | group: ${{ github.workflow }}-${{ github.ref }} 14 | cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} 15 | 16 | env: 17 | # This will let tools make use of the full palette of 18 | # 256 colours. 19 | FORCE_COLOR: "3" 20 | 21 | jobs: 22 | style: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v6 26 | - name: Set up uv 27 | uses: astral-sh/setup-uv@v7 28 | with: 29 | version: "latest" 30 | enable-cache: true 31 | cache-dependency-glob: "**/pyproject.toml" 32 | 33 | - name: Check style 34 | run: uvx pre-commit run -a 35 | 36 | template_test: 37 | needs: style 38 | runs-on: ${{ matrix.os }} 39 | strategy: 40 | fail-fast: false 41 | matrix: 42 | os: [ubuntu-latest, macos-13, macos-14, windows-latest] 43 | python-version: ["3.9", "3.10", "3.11", "3.12"] 44 | name: 45 | Template Generation/Project Tests (${{ matrix.os }} / Python ${{ matrix.python-version }}) 46 | steps: 47 | - name: Checkout pybamm-cookie 48 | uses: actions/checkout@v6 49 | 50 | - name: Set up uv 51 | uses: astral-sh/setup-uv@v7 52 | with: 53 | version: "latest" 54 | python-version: ${{ matrix.python-version }} 55 | activate-environment: true 56 | enable-cache: true 57 | cache-dependency-glob: "**/pyproject.toml" 58 | 59 | - name: Install nox 60 | run: uv tool install nox 61 | 62 | - name: Set up Git 63 | run: | 64 | git config --global user.name "github-actions[bot]" 65 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 66 | 67 | - name: Test template generation 68 | run: nox -s template-tests --verbose 69 | 70 | - name: Run coverage tests 71 | if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' 72 | run: nox -s coverage --verbose 73 | 74 | - name: Upload coverage report 75 | if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' 76 | uses: codecov/codecov-action@v5.5.2 77 | with: 78 | token: ${{ secrets.CODECOV_TOKEN }} 79 | 80 | run_doctests: 81 | needs: style 82 | runs-on: ubuntu-latest 83 | name: Doctests (ubuntu-latest / Python 3.12) 84 | 85 | steps: 86 | - name: Check out pybamm-cookie repository 87 | uses: actions/checkout@v6 88 | with: 89 | fetch-depth: 0 90 | 91 | - name: Set up uv 92 | uses: astral-sh/setup-uv@v7 93 | with: 94 | version: "latest" 95 | enable-cache: true 96 | cache-dependency-glob: "**/pyproject.toml" 97 | 98 | - name: Set up Git 99 | run: | 100 | git config --global user.name "github-actions[bot]" 101 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 102 | 103 | - name: Check if the documentation can be built 104 | run: uvx nox -s docs --verbose 105 | 106 | generated_project_tests: 107 | needs: [template_test] 108 | runs-on: ${{ matrix.os }} 109 | strategy: 110 | fail-fast: false 111 | matrix: 112 | os: [ubuntu-latest, macos-13, macos-14, windows-latest] 113 | python-version: ["3.9", "3.10", "3.11", "3.12"] 114 | backend: [hatch, setuptools] 115 | vcs: [true, false] 116 | 117 | name: Generated Project Tests (${{ matrix.os }} / Python ${{ matrix.python-version }} / Backend ${{ matrix.backend }} / VCS ${{ matrix.vcs }}) 118 | 119 | steps: 120 | - name: Checkout pybamm-cookie 121 | uses: actions/checkout@v6 122 | 123 | - name: Set up uv 124 | uses: astral-sh/setup-uv@v7 125 | with: 126 | version: "latest" 127 | python-version: ${{ matrix.python-version }} 128 | activate-environment: true 129 | enable-cache: true 130 | cache-dependency-glob: "**/pyproject.toml" 131 | 132 | - name: Install dependencies 133 | run: | 134 | uv pip install copier jinja2_time 135 | uv tool install nox 136 | 137 | - name: Generate project 138 | run: copier copy . ../ --data project_name=pybamm-${{ matrix.backend }}-${{ matrix.vcs }} --data project_slug=pybamm_${{ matrix.backend }}_${{ matrix.vcs }} --data backend=${{ matrix.backend }} --data vcs=${{ matrix.vcs }} --trust --defaults 139 | 140 | - name: Test the generated project 141 | working-directory: ../pybamm-${{ matrix.backend }}-${{ matrix.vcs }} 142 | run: nox -s generated-project-tests --verbose 143 | 144 | run_generated_project_doctests: 145 | needs: [template_test] 146 | runs-on: ubuntu-latest 147 | name: Generated Project Doctests (ubuntu-latest / Python 3.12) 148 | 149 | steps: 150 | - name: Check out pybamm-cookie repository 151 | uses: actions/checkout@v6 152 | with: 153 | fetch-depth: 0 154 | python-version: 3.12 155 | 156 | - name: Set up uv 157 | uses: astral-sh/setup-uv@v7 158 | with: 159 | version: "latest" 160 | python-version: 3.12 161 | activate-environment: true 162 | enable-cache: true 163 | cache-dependency-glob: "**/pyproject.toml" 164 | 165 | - name: Install dependencies 166 | run: uv pip install copier jinja2_time 167 | 168 | - name: Install copier and jinja2_time and generate a template with default values 169 | run: copier copy . . --trust --defaults 170 | 171 | - name: Set up Git 172 | run: | 173 | git config --global user.name "github-actions[bot]" 174 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 175 | 176 | - name: Check if the documentation can be built 177 | working-directory: ./pybamm-example-project 178 | run: | 179 | git add . 180 | git commit -am "initial commit" 181 | uvx nox -s docs --verbose 182 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/entry_point.py.jinja: -------------------------------------------------------------------------------- 1 | """ 2 | This code is adopted from the PyBaMM project under the BSD-3-Clause 3 | 4 | Copyright (c) 2018-2024, the PyBaMM team. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | """ 32 | 33 | 34 | import importlib.metadata 35 | import sys 36 | import textwrap 37 | from collections.abc import Mapping 38 | from typing import Callable 39 | 40 | class EntryPoint(Mapping): 41 | """ 42 | Dict-like interface for accessing parameter sets and models through entry points in copier template. 43 | Access via :py:data:`{{project_slug}}.parameter_sets` for parameter_sets 44 | Access via :py:data:`{{project_slug}}.Model` for Models 45 | 46 | Examples 47 | -------- 48 | Listing available parameter sets: 49 | >>> import {{project_slug}} 50 | >>> list({{project_slug}}.parameter_sets) 51 | ['Chen2020', ...] 52 | >>> list({{project_slug}}.models) 53 | ['SPM', ...] 54 | 55 | Get the docstring for a parameter set/model: 56 | 57 | 58 | >>> print({{project_slug}}.parameter_sets.get_docstring("Ai2020")) 59 | 60 | Parameters for the Enertech cell (Ai2020), from the papers :footcite:t:`Ai2019`, 61 | :footcite:t:`rieger2016new` and references therein. 62 | ... 63 | 64 | >>> print({{project_slug}}.models.get_docstring("SPM")) 65 | 66 | Single Particle Model (SPM) model of a lithium-ion battery, from :footcite:t:`Marquis2019`. This class differs from the :class:`pybamm.lithium_ion.SPM` model class in that it shows the whole model in a single class. This comes at the cost of flexibility in combining different physical effects, and in general the main SPM class should be used instead. 67 | ... 68 | See also: :ref:`adding-parameter-sets` 69 | """ 70 | 71 | _instances = 0 72 | def __init__(self, group): 73 | """Dict of entry points for parameter sets or models, lazily load entry points as""" 74 | if not hasattr(self, 'initialized'): # Ensure __init__ is called once per instance 75 | self.initialized = True 76 | EntryPoint._instances += 1 77 | self._all_entries = dict() 78 | self.group = group 79 | for entry_point in self.get_entries(self.group): 80 | self._all_entries[entry_point.name] = entry_point 81 | 82 | @staticmethod 83 | def get_entries(group_name): 84 | """Wrapper for the importlib version logic""" 85 | if sys.version_info < (3, 10): # pragma: no cover 86 | return importlib.metadata.entry_points()[group_name] 87 | else: 88 | return importlib.metadata.entry_points(group=group_name) 89 | 90 | def __new__(cls, group): 91 | """Ensure only two instances of entry points exist, one for parameter sets and the other for models""" 92 | if EntryPoint._instances < 2: 93 | cls.instance = super().__new__(cls) 94 | return cls.instance 95 | 96 | def __getitem__(self, key) -> dict: 97 | return self._load_entry_point(key)() 98 | 99 | def _load_entry_point(self, key) -> Callable: 100 | """Check that ``key`` is a registered ``parameter_sets`` or ``models` , 101 | and return the entry point for the parameter set/model, loading it needed.""" 102 | if key not in self._all_entries: 103 | raise KeyError(f"Unknown parameter set or model: {key}") 104 | ps = self._all_entries[key] 105 | try: 106 | ps = self._all_entries[key] = ps.load() 107 | except AttributeError: 108 | pass 109 | return ps 110 | 111 | def __iter__(self): 112 | return self._all_entries.__iter__() 113 | 114 | def __len__(self) -> int: 115 | return len(self._all_entries) 116 | 117 | def get_docstring(self, key): 118 | """Return the docstring for the ``key`` parameter set or model""" 119 | return textwrap.dedent(self._load_entry_point(key).__doc__) 120 | 121 | def __getattribute__(self, name): 122 | try: 123 | return super().__getattribute__(name) 124 | except AttributeError as error: 125 | raise error 126 | 127 | #: Singleton Instance of :class:ParameterSets """ 128 | parameter_sets = EntryPoint(group="parameter_sets") 129 | 130 | #: Singleton Instance of :class:ModelEntryPoints""" 131 | models = EntryPoint(group="models") 132 | 133 | def Model(model:str): 134 | """ 135 | Returns the loaded model object 136 | 137 | Parameters 138 | ---------- 139 | model : str 140 | The model name or author name of the model mentioned at the model entry point. 141 | Returns 142 | ------- 143 | pybamm.model 144 | Model object of the initialised model. 145 | Examples 146 | -------- 147 | Listing available models: 148 | >>> import {{project_slug}} 149 | >>> list({{project_slug}}.models) 150 | ['SPM', ...] 151 | >>> {{project_slug}}.Model('Author/Year') 152 | <{{project_slug}}.models.input.SPM.SPM object> 153 | """ 154 | return models[model] 155 | -------------------------------------------------------------------------------- /template/{{ project_name }}/docs/conf.py.jinja: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file contains an opinionated list of extensions and configuration options 4 | # used by the PyBaMM documentation. 5 | # 6 | # For a full list, see the Sphinx documentation for configuration options at 7 | # https://www.sphinx-doc.org/en/master/config 8 | # 9 | # More information about the configuration options used here can be found in the 10 | # configuration file for the PyBaMM documentation at 11 | # https://github.com/pybamm-team/PyBaMM/blob/develop/docs/conf.py 12 | # 13 | # The configuration options to adjust the PyData Sphinx Theme with can be found at 14 | # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/index.html 15 | 16 | 17 | import importlib.metadata 18 | import sys 19 | from pathlib import Path 20 | 21 | # ---- Project information ------------------------------------------------------------ 22 | project = "{{ project_name }}" 23 | copyright = "{% now 'utc', '%Y' %}, {{ full_name }}" 24 | author = "{{ full_name }}" 25 | version = release = importlib.metadata.version("{{ project_slug }}") 26 | 27 | # ---- Path configuration ------------------------------------------------------------- 28 | 29 | # Path for repository root 30 | sys.path.insert(0, Path("../").resolve()) 31 | 32 | # Path for local Sphinx extensions 33 | sys.path.append(Path("./sphinxext/").resolve()) 34 | 35 | # ---- General configuration ---------------------------------------------------------- 36 | 37 | # If your documentation needs a minimal Sphinx version, state it here. 38 | 39 | # needs_sphinx = '1.0' 40 | 41 | # The suffix(es) of source filenames. You may specify multiple suffixes as 42 | # a list of strings. 43 | source_suffix = [".rst", ".md"] 44 | 45 | # List of patterns relative to the source directory that match files and 46 | # directories to ignore when looking for source files. This pattern also 47 | # affects the html_static_path and html_extra_path configuration options. 48 | exclude_patterns = [ 49 | "_build", 50 | "**.ipynb_checkpoints", 51 | "Thumbs.db", 52 | ".DS_Store", 53 | ] 54 | 55 | html_theme = "pydata_sphinx_theme" 56 | html_title = f"{project} v{version} Manual" 57 | html_last_updated_fmt = "%Y-%m-%d" 58 | html_static_path = ["_static"] 59 | html_file_suffix = ".html" 60 | 61 | # For edit button 62 | html_context = { 63 | "github_user": "{{org}}", 64 | "github_repo": "{{project_name}}", 65 | "github_version": "{{branch}}", 66 | "doc_path": "docs/", 67 | } 68 | # Add any logos and favicons for your hosted documentation here. The logo and the favicon 69 | # should be placed in the html_static_path directory listed above. 70 | # html_logo = "_static/logo.png" 71 | # html_favicon = "_static/favicon.png" 72 | 73 | # Add any paths that contain custom static files (such as style sheets or JavaScript scripts) 74 | # in the html_static_path listed above. They are copied after the builtin static files, so a 75 | # file named "default.css" will overwrite the builtin "default.css". 76 | # html_css_files = ["custom.css"] 77 | # html_js_files = ["custom.js"] 78 | 79 | # Suppress any warnings generated by Sphinx and/or by Sphinx extensions as 80 | # a list of strings. The following warnings are suppressed by default: 81 | suppress_warnings = ["git.too_shallow"] 82 | 83 | # Add any paths that contain templates here, relative to this directory. 84 | templates_path = ["_templates"] 85 | 86 | # The language for content autogenerated by Sphinx. Refer to the Sphinx documentation 87 | # for a list of supported language codes according to the IETF BCP 47 standard. 88 | language = "en" 89 | 90 | # Add any Sphinx extension module names here in a list of strings. They can be 91 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. The 92 | # custom ones must be placed under the path specified for local Sphinx extensions 93 | # in the system path configuration above. 94 | 95 | extensions = [ 96 | # Sphinx extensions 97 | "sphinx.ext.autodoc", 98 | "sphinx.ext.intersphinx", 99 | "sphinx.ext.mathjax", 100 | "sphinx.ext.napoleon", 101 | # Local extensions under ./sphinxext/ 102 | # Third-party extensions 103 | "myst_parser", 104 | "sphinx_design", 105 | "sphinx_copybutton", 106 | "sphinx_inline_tabs", 107 | "sphinxcontrib.bibtex", 108 | "sphinx_last_updated_by_git", 109 | "pydata_sphinx_theme", 110 | "nbsphinx", 111 | "IPython.sphinxext.ipython_console_highlighting", 112 | ] 113 | 114 | # Configure references 115 | bibtex_bibfiles = ['refs.bib'] 116 | # ---- Options for EPUB output -------------------------------------------------------- 117 | 118 | # Bibliographic Dublin Core information 119 | epub_title = project 120 | 121 | # The unique identifier of the text. This can be a ISBN number or the project homepage 122 | # epub_identifier = '' 123 | 124 | # A unique identification for the text 125 | # epub_uid = '' 126 | 127 | # A list of files that should not be packed into the EPUB file 128 | epub_exclude_files = ["search.html"] 129 | 130 | # ---- HTML theme configuration ------------------------------------------------------- 131 | 132 | # Theme options are theme-specific and customize the look and feel of a theme further. 133 | # For a list of options available for each theme, see the documentation for the theme. 134 | 135 | # For a list of options available for the PyData Sphinx Theme, see the documentation at 136 | # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/index.html 137 | 138 | html_theme_options = { 139 | # "logo": { 140 | # "image_light": "logo.png", 141 | # "image_dark": "logo.png", 142 | # }, 143 | "icon_links": [ 144 | { 145 | {%- if platform == "github" %} 146 | "name": "GitHub", 147 | "icon": "fa-brands fa-square-github", 148 | {%- elif platform == "gitlab" %} 149 | "name": "GitLab", 150 | "icon": "fa-brands fa-square-gitlab", 151 | {%- endif %} 152 | "url": "{{ url }}", 153 | }, 154 | { 155 | "name": "PyPI", 156 | "url": "https://pypi.org/project/{{ project_name }}/", 157 | "icon": "fa-solid fa-box", 158 | }, 159 | ], 160 | "collapse_navigation": True, 161 | "navbar_end": ["theme-switcher", "navbar-icon-links"], 162 | "use_edit_page_button": True, 163 | "pygment_light_style": "xcode", 164 | "pygment_dark_style": "monokai", 165 | "footer_start": [ 166 | "copyright", 167 | "sphinx-version", 168 | ], 169 | "footer_end": [ 170 | "theme-version", 171 | "last-updated", 172 | ], 173 | } 174 | 175 | # ---- Extension configuration -------------------------------------------------------- 176 | 177 | # Add any configuration options for Sphinx extensions here as per the documentation for 178 | # each extension. See the PyBaMM documentation at 179 | # https://github.com/pybamm-team/PyBaMM/blob/develop/docs/conf.py for examples of how 180 | # to configure Sphinx extensions for your project. 181 | 182 | myst_enable_extensions = [ 183 | "colon_fence", 184 | ] 185 | 186 | intersphinx_mapping = { 187 | "python": ("https://docs.python.org/3", None), 188 | "numpy": ("https://numpy.org/doc/stable/", None), 189 | "scipy": ("https://docs.scipy.org/doc/scipy/", None), 190 | "matplotlib": ("https://matplotlib.org/stable", None), 191 | "pybamm": ("https://docs.pybamm.org/en/latest/", None), 192 | } 193 | 194 | always_document_param_types = True 195 | napoleon_use_rtype = True 196 | napoleon_google_docstring = False 197 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/models/input/BasicReservoir.py: -------------------------------------------------------------------------------- 1 | """ 2 | This code is adopted from the PyBaMM project under the BSD-3-Clause 3 | 4 | Copyright (c) 2018-2024, the PyBaMM team. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | """ 32 | 33 | 34 | # 35 | # Basic Reservoir Model 36 | # 37 | import pybamm 38 | 39 | class BasicReservoir(pybamm.lithium_ion.BaseModel): 40 | """Reservoir model of a lithium-ion battery, from 41 | :footcite:t:`Marquis2019`. 42 | 43 | Parameters 44 | ---------- 45 | name : str, optional 46 | The name of the model. 47 | """ 48 | 49 | def __init__(self, name="Reservoir Model"): 50 | super().__init__({}, name) 51 | pybamm.citations.register("Marquis2019") 52 | # `param` is a class containing all the relevant parameters and functions for 53 | # this model. These are purely symbolic at this stage, and will be set by the 54 | # `ParameterValues` class when the model is processed. 55 | param = self.param 56 | 57 | ###################### 58 | # Variables 59 | ###################### 60 | # Variables that depend on time only are created without a domain 61 | Q = pybamm.Variable("Discharge capacity [A.h]") 62 | # Variables that vary spatially are created with a domain 63 | sto_n = pybamm.Variable( 64 | "Average negative particle stoichiometry", 65 | domain="current collector", 66 | bounds=(0, 1), 67 | ) 68 | sto_p = pybamm.Variable( 69 | "Average positive particle stoichiometry", 70 | domain="current collector", 71 | bounds=(0, 1), 72 | ) 73 | 74 | # Constant temperature 75 | T = param.T_init 76 | 77 | ###################### 78 | # Other set-up 79 | ###################### 80 | 81 | # Current density 82 | i_cell = param.current_density_with_time 83 | a_n = 3 * param.n.prim.epsilon_s_av / param.n.prim.R_typ 84 | a_p = 3 * param.p.prim.epsilon_s_av / param.p.prim.R_typ 85 | j_n = i_cell / (param.n.L * a_n) 86 | j_p = -i_cell / (param.p.L * a_p) 87 | 88 | ###################### 89 | # State of Charge 90 | ###################### 91 | I = param.current_with_time 92 | # The `rhs` dictionary contains differential equations, with the key being the 93 | # variable in the d/dt 94 | self.rhs[Q] = I / 3600 95 | # Initial conditions must be provided for the ODEs 96 | self.initial_conditions[Q] = pybamm.Scalar(0) 97 | 98 | ###################### 99 | # Particles 100 | ###################### 101 | 102 | self.rhs[sto_n] = -i_cell / ( 103 | param.n.L * param.n.prim.epsilon_s_av * param.n.prim.c_max * param.F 104 | ) 105 | self.rhs[sto_p] = i_cell / ( 106 | param.p.L * param.p.prim.epsilon_s_av * param.p.prim.c_max * param.F 107 | ) 108 | # c_n_init and c_p_init are functions of r and x, but for the reservoir model 109 | # we take the x-averaged and r-averaged value since there are no x-dependence 110 | # nor r-dependencein the particles 111 | self.initial_conditions[sto_n] = ( 112 | pybamm.x_average(pybamm.r_average(param.n.prim.c_init)) / param.n.prim.c_max 113 | ) 114 | self.initial_conditions[sto_p] = ( 115 | pybamm.x_average(pybamm.r_average(param.p.prim.c_init)) / param.p.prim.c_max 116 | ) 117 | 118 | self.events += [ 119 | pybamm.Event( 120 | "Minimum negative particle surface stoichiometry", 121 | sto_n - 0.01, 122 | ), 123 | pybamm.Event( 124 | "Maximum negative particle surface stoichiometry", 125 | (1 - 0.01) - sto_n, 126 | ), 127 | pybamm.Event( 128 | "Minimum positive particle surface stoichiometry", 129 | sto_p - 0.01, 130 | ), 131 | pybamm.Event( 132 | "Maximum positive particle surface stoichiometry", 133 | (1 - 0.01) - sto_p, 134 | ), 135 | ] 136 | 137 | # Note that the reservoir model does not have any algebraic equations, so the 138 | # `algebraic` dictionary remains empty 139 | 140 | ###################### 141 | # (Some) variables 142 | ###################### 143 | # Interfacial reactions 144 | RT_F = param.R * T / param.F 145 | j0_n = param.n.prim.j0(param.c_e_init_av, sto_n * param.n.prim.c_max, T) 146 | j0_p = param.p.prim.j0(param.c_e_init_av, sto_p * param.p.prim.c_max, T) 147 | eta_n = (2 / param.n.prim.ne) * RT_F * pybamm.arcsinh(j_n / (2 * j0_n)) 148 | eta_p = (2 / param.p.prim.ne) * RT_F * pybamm.arcsinh(j_p / (2 * j0_p)) 149 | phi_s_n = 0 150 | phi_e = -eta_n - param.n.prim.U(sto_n, T) 151 | phi_s_p = eta_p + phi_e + param.p.prim.U(sto_p, T) 152 | V = phi_s_p 153 | num_cells = pybamm.Parameter( 154 | "Number of cells connected in series to make a battery" 155 | ) 156 | c_s_n = sto_n * param.n.prim.c_max 157 | c_s_p = sto_p * param.p.prim.c_max 158 | 159 | whole_cell = ["negative electrode", "separator", "positive electrode"] 160 | # The `variables` dictionary contains all variables that might be useful for 161 | # visualising the solution of the model 162 | # Primary broadcasts are used to broadcast scalar quantities across a domain 163 | # into a vector of the right shape, for multiplying with other vectors 164 | self.variables = { 165 | "Time [s]": pybamm.t, 166 | "Discharge capacity [A.h]": Q, 167 | "X-averaged negative particle concentration [mol.m-3]": pybamm.PrimaryBroadcast( 168 | c_s_n, "negative particle" 169 | ), 170 | "Negative particle surface " 171 | "concentration [mol.m-3]": pybamm.PrimaryBroadcast( 172 | c_s_n, "negative electrode" 173 | ), 174 | "Electrolyte concentration [mol.m-3]": pybamm.PrimaryBroadcast( 175 | param.c_e_init_av, whole_cell 176 | ), 177 | "X-averaged positive particle concentration [mol.m-3]": pybamm.PrimaryBroadcast( 178 | c_s_p, "positive particle" 179 | ), 180 | "Positive particle surface " 181 | "concentration [mol.m-3]": pybamm.PrimaryBroadcast( 182 | c_s_p, "positive electrode" 183 | ), 184 | "Current [A]": I, 185 | "Current variable [A]": I, # for compatibility with pybamm.Experiment 186 | "Negative electrode potential [V]": pybamm.PrimaryBroadcast( 187 | phi_s_n, "negative electrode" 188 | ), 189 | "Electrolyte potential [V]": pybamm.PrimaryBroadcast(phi_e, whole_cell), 190 | "Positive electrode potential [V]": pybamm.PrimaryBroadcast( 191 | phi_s_p, "positive electrode" 192 | ), 193 | "Voltage [V]": V, 194 | "Battery voltage [V]": V * num_cells, 195 | } 196 | # Events specify points at which a solution should terminate 197 | self.events += [ 198 | pybamm.Event("Minimum voltage [V]", V - param.voltage_low_cut), 199 | pybamm.Event("Maximum voltage [V]", param.voltage_high_cut - V), 200 | ] 201 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to `pybamm-cookie` 2 | 3 | If you'd like to contribute to this project, please have a look at the [guidelines below](#workflow). 4 | 5 | If you're already familiar with our workflow, maybe have a quick look at the [pre-commit checks](#pre-commit-checks) directly below. 6 | 7 | ## `pre-commit` checks 8 | 9 | Before you commit any code, please perform the following checks: 10 | 11 | - [All tests pass](#testing): `$ nox -s test-generation` 12 | - [The documentation builds](#building-the-documentation): `$ nox -s docs` 13 | 14 | ### Installing and using pre-commit 15 | 16 | `pybamm-cookie` uses a set of `pre-commit` hooks and the `pre-commit` bot to format and prettify the codebase. The hooks can be installed locally using - 17 | 18 | ```bash 19 | pip install pre-commit 20 | pre-commit install 21 | ``` 22 | 23 | This would run the checks every time a commit is created locally. The checks will only run on the files modified by that commit, but the checks can be triggered for all the files using - 24 | 25 | ```bash 26 | pre-commit run --all-files 27 | ``` 28 | 29 | If you would like to skip the failing checks and push the code for further discussion, use the `--no-verify` option with `git commit`. 30 | 31 | ## Workflow 32 | 33 | We use [Git](https://en.wikipedia.org/wiki/Git) and [GitHub](https://en.wikipedia.org/wiki/GitHub) to coordinate our work. When making any kind of update, we try to follow the procedure below. 34 | 35 | ### A. Before you begin 36 | 37 | 1. Create an [issue](https://guides.github.com/features/issues/) where new proposals can be discussed before any coding is done. 38 | 2. Create a [branch](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) of this repo (ideally on your own [fork](https://help.github.com/articles/fork-a-repo/)), where all changes will be made. 39 | 3. Download the source code onto your local system, by [cloning](https://help.github.com/articles/cloning-a-repository/) the repository (or your fork of the repository). 40 | 4. Use `nox -s dev` or `pip install -e .[dev]` to install `pybamm-cookie` in editable/development mode. 41 | 5. [Test](#testing) if your installation worked, using the test script: `nox -s test-generation` or `pytest`. 42 | 43 | You now have everything you need to start making changes! 44 | 45 | ### B. Writing your code 46 | 47 | 6. This project is developed in [Python](https://www.python.org)), and uses the [copier](https://copier.readthedocs.io/) templating tool. For testing, we use [`pytest`](https://docs.pytest.org/en/). 48 | 7. Make sure to follow our [coding style guidelines](#coding-style-guidelines). 49 | 8. Commit your changes to your branch with [useful, descriptive commit messages](https://chris.beams.io/posts/git-commit/): Remember these are 50 | publicly visible and should still make sense a few months ahead in time. 51 | While developing, you can keep using the GitHub issue you're working on 52 | as a place for discussion. 53 | 54 | ### C. Merging your changes with `pybamm-cookie` 55 | 56 | 9. [Test your code!](#testing) 57 | 10. When you feel your code is finished, or at least warrants serious discussion, run the [pre-commit checks](#pre-commit-checks) and then create a [pull request](https://help.github.com/articles/about-pull-requests/) (PR) on [`pybamm-cookie`'s GitHub page](https://github.com/pybamm-team/pybamm-cookie). 58 | 11. Once a PR has been created, it will be reviewed by any member of the community. Changes might be suggested which you can make by simply adding new commits to the branch. When everything's finished, someone with the right GitHub permissions will merge your changes into pybamm-cookie main repository. 59 | 60 | 61 | ## Coding style guidelines 62 | 63 | This project follows the [PEP8 recommendations](https://www.python.org/dev/peps/pep-0008/) for coding style. These are very common guidelines, and community tools have been developed to check how well projects implement them. We recommend using pre-commit hooks to check your code before committing it. See [installing and using pre-commit](#installing-and-using-pre-commit) section for more details. 64 | 65 | ### Ruff 66 | 67 | We use [ruff](https://github.com/astral-sh/ruff) to check our PEP8 adherence. To try this on your system, navigate to the parent pybamm-cookie directory in a console and type 68 | 69 | ```bash 70 | python -m pip install pre-commit 71 | pre-commit run ruff 72 | ``` 73 | 74 | Ruff is configured inside the file `pre-commit-config.yaml`, allowing us to ignore some errors. If you think some rules should be added or removed, please submit an [issue](https://github.com/pybamm-team/pybamm-cookie/issues). 75 | 76 | If you performed the `pre-commit install` step above, your code changes will be checked against Ruff automatically when you try to commit them (see [Pre-commit checks](#pre-commit-checks)). 77 | 78 | 79 | ## Testing 80 | 81 | All code requires testing. We use the [Pytest](https://docs.pytest.org/en/) package for our tests. (These tests typically just check that the code runs without error, and so, are more _debugging_ than _testing_ in a strict sense. Nevertheless, they are very useful to have!). 82 | 83 | If you have `nox` installed, to run tests for the template, type 84 | 85 | ```bash 86 | nox -s template-tests 87 | ``` 88 | 89 | else, type 90 | 91 | ```bash 92 | pytest tests/ 93 | ``` 94 | 95 | To test a generated project, meaning a project generated out of `pybamm-cookie`, you can simply run 96 | ```bash 97 | nox -s generated-project-tests 98 | ``` 99 | 100 | ### Writing tests 101 | 102 | Every new feature should have its own test. To create ones, have a look at the `test` directory and see if there's a test for a similar method. Copy-pasting this is a good way to start. 103 | 104 | Next, add some simple (and speedy!) tests of your main features. If these run without exceptions, that's a good start! Next, check the output of your methods using any of these [assert methods](https://docs.pytest.org/en/stable/how-to/assert.html). 105 | 106 | 107 | ## Documentation 108 | 109 | First and foremost, every method and every class should have a [docstring](https://www.python.org/dev/peps/pep-0257/) that describes in plain terms what it does, and what the expected input and output is. 110 | 111 | These docstrings can be fairly simple, but can also make use of [reStructuredText](http://docutils.sourceforge.net/docs/user/rst/quickref.html), a markup language designed specifically for writing [technical documentation](https://en.wikipedia.org/wiki/ReStructuredText). 112 | 113 | Using [Sphinx](http://www.sphinx-doc.org/en/stable/) the documentation in `docs` can be converted to HTML, PDF, and other formats. In particular, we use it to generate the documentation on http://docs.pybamm.org/ 114 | 115 | ### Building the documentation 116 | 117 | To test and debug the documentation, it's best to build it locally. To do this, navigate to your pybamm-cookie directory in a console, and then type: 118 | 119 | ``` 120 | nox -s docs 121 | ``` 122 | 123 | And then visit the webpage served at `http://127.0.0.1:8000`. Each time a change to the documentation source is detected, the HTML is rebuilt and the browser automatically reloaded. In CI, the docs are built and tested using the `docs` session in the `noxfile.py` file with warnings turned into errors, to fail the build. The warnings can be removed or ignored by adding the appropriate warning identifier to the `suppress_warnings` list in `docs/conf.py`. 124 | 125 | ### Continuous Integration using GitHub Actions 126 | 127 | Each change pushed to the `pybamm-cookie` GitHub repository will trigger the tests to be run, using [GitHub Actions](https://github.com/features/actions). 128 | 129 | Tests are run for different operating systems, and for all Python versions officially supported by the `pybamm-cookie` template. If you open a pull request (PR), feedback is directly available on the corresponding page. If all tests pass, a green tick will be displayed next to the corresponding test run. If one or more test(s) fail, a red cross will be displayed instead. 130 | 131 | More details can be obtained by clicking on a specific run. 132 | 133 | Configuration files for various GitHub Actions workflows can be found in `.github/workflows/`. 134 | 135 | ### GitHub 136 | 137 | GitHub does some magic with particular filenames. In particular: 138 | 139 | - The first page people see when they go to [our GitHub page](https://github.com/pybamm-team/pybamm-cookie) displays the contents of [README.md](https://github.com/pybamm-team/pybamm-cookie/blob/main/README.md), which is written in the [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) format. Some guidelines can be found [here](https://help.github.com/articles/about-readmes/). 140 | - The license for using pybamm-cookie is stored in [LICENSE](https://github.com/pybamm-team/pybamm-cookie/blob/main/LICENSE.txt), and [automatically](https://help.github.com/articles/adding-a-license-to-a-repository/) linked to by GitHub. 141 | - This file, [CONTRIBUTING.md](https://github.com/pybamm-team/pybamm-cookie/blob/main/CONTRIBUTING.md) is recognised as the document that lists the contribution guidelines and a link is [automatically](https://github.com/blog/1184-contributing-guidelines) displayed when new issues or pull requests are created. 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pybamm-cookie 2 | 3 | 4 | 5 | 25 | 26 | ![pybamm-cookie](docs/_static/pybammcookiewhite.png) 27 | 28 | [![Powered by NumFOCUS](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A)](http://numfocus.org) 29 | [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-red.json)](https://github.com/copier-org/copier) 30 | [![pybamm-cookie](https://img.shields.io/badge/%F0%9F%8D%AA%20pybamm--cookie-cf4c4c?style=flat&link=https%3A%2F%2Fgithub.com%2Fpybamm-team%2Fpybamm-cookie)](https://github.com/pybamm-team/pybamm-cookie) 31 | [![PyPI](https://img.shields.io/badge/PyPI-white?style=flat&logo=pypi&link=https%3A%2F%2Fpypi.org%2Fproject%2Fpybamm-cookie%2F)](https://pypi.org/project/pybamm-cookie/) 32 | [![Test template and generated project](https://github.com/pybamm-team/pybamm-cookie/actions/workflows/test_on_push.yml/badge.svg)](https://github.com/pybamm-team/pybamm-cookie/actions/workflows/test_on_push.yml) 33 | 34 | This repository contains a `copier` template for battery modeling projects using PyBaMM, released under the [BSD-3-Clause license](https://github.com/pybamm-team/pybamm-cookie/blob/main/LICENSE). Currently under active development. 35 | 36 | ## 📄 Using `pybamm-cookie` 37 | 38 | ### Generating projects with `pybamm-cookie` 39 | 40 | #### Manually using copier 41 | 42 | Install `copier` and `jinja2_time` extension using `pip`. 43 | ```bash 44 | pip install copier jinja2-time 45 | ``` 46 | Generate a project from the `pybamm-cookie` template. 47 | 48 | ```bash 49 | copier copy https://github.com/pybamm-team/pybamm-cookie.git . --trust 50 | # this will generate the project in the current working directory 51 | copier copy https://github.com/pybamm-team/pybamm-cookie.git path_to_copy_to/ --trust 52 | # this will generate the project in the specified path 53 | ``` 54 | #### Using pipx (recommended) 55 | 56 | You can generate a project by executing the `pipx run` command which doesn't need any package installations. 57 | ```bash 58 | pipx run pybamm-cookie --path /path_to_copy_to 59 | ``` 60 | 61 | Or if you wish to install the `pybamm-cookie` package and then generate a project, you could do so with the help of following commands. 62 | ```bash 63 | pipx install pybamm-cookie # or pip install pybamm-cookie 64 | ``` 65 | Navigate into the directory you want your project directory to reside in, or use `--path` argument to explicitly mention the path where you want your project to be generated. 66 | ```bash 67 | pybamm-cookie --path /path_to_copy_to 68 | ``` 69 | #### Using pip/pip inside venv 70 | 71 | You can also perform a normal `pip` installation for the `pybamm-cookie` CLI and generate a project. 72 | ```bash 73 | pip install pybamm-cookie 74 | pybamm-cookie 75 | ``` 76 | 77 | Copier will prompt you with various configurations and you may choose the ones that suit your use case. 78 | Additionally you can perform `pybamm-cookie -h` to know the list of actions you can perform with the CLI. 79 | 80 | > [!NOTE] 81 | > A `git` repository is automatically initialised when a project is created within a directory. To push the contents to the upstream GitHub repository, create a GitHub repository with the same name as your local repository and do not initialise your GitHub repository with any files such as licenses or README which might conflict with the local repository, follow these steps as listed in the [GitHub documentation](https://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github#adding-a-local-repository-to-github-using-git). 82 | 83 | After generation, you can navigate to the generated project and run `nox -s generated-project-tests` to ensure if the project units are working as intended. 84 | 85 | ### Installing the `pybamm-cookie` project 86 | 87 | This refers to the project used for the development of this template. There are two ways to install this project: either through `nox` or `pip`. `nox` uses `uv pip` or `pip` internally, and in this case, creates a virtual environment for you to activate. 88 | To install, navigate to the root directory of this repository and execute either of these commands: 89 | 90 | `nox -s dev` 91 | or 92 | `pip install -e .[dev]` 93 | 94 | To check if the project was successfully installed, import the project inside Python. 95 | 96 | ```python 97 | import pybamm_cookie 98 | 99 | pybamm_cookie.__version__ 100 | ``` 101 | ### Project Layout 102 | ```bash 103 | . 104 | ├── .github 105 | │   └── workflows 106 | ├── docs 107 | │   └── _static 108 | ├── src 109 | │   ├── pybamm_example_project 110 | │   ├── models 111 | │   │   └── input 112 | │   └─ parameters 113 | │      └── input 114 | ├── tests 115 | │ ├── generated_project_tests 116 | │ └── user_tests 117 | ├─ noxfile.py 118 | └─ pyproject.toml 119 | ``` 120 | A basic generated project with `pybamm-cookie` has a directory structure like the one depicted above. Each directory has a special purpose and is highly recommended to use them for their specific purposes to avoid any errors. 121 | - `docs/` contains the basic configuration for building documentation using [sphinx](https://www.sphinx-doc.org/). 122 | - `src/` contains the main package files under a directory with your specified project name. This is where all your code should be written. 123 | - `models/input/` - Contains the source code for battery models. Refer [PyBaMM models](https://docs.pybamm.org/en/latest/source/api/models/index.html) to learn how to write your own battery models. 124 | - `parameters/input/` - Contains the source code for parameters sets. Refer [PyBaMM parameter sets](https://docs.pybamm.org/en/stable/source/api/parameters/parameter_sets.html) to learn more on parameter sets. 125 | - `tests/` The tests directory contains two sub-directories - 126 | - `generated_project_tests/` - Contains pre-defined tests for verifying if the units inside generated project work well. It can be verified using `nox -s generated-project-tests` or `pytest tests/generated_project_tests` command. 127 | - `user_tests/` - This directory contains all the user written tests, the example tests can be copied and modified as per your own needs. We suggest you use [pytest](https://docs.pytest.org/en/stable/) to write tests. The tests can be then run by executing `nox -s user-tests` or `pytest tests/user_tests`. 128 | - `noxfile.py` contains basic `nox sessions` for building documentation and runnings tests. 129 | - `pyproject.toml` has project metadata and build backend configurations. 130 | - `github/workflows/` has all the basic CI configurations to automate tests and builds on [GitHub Actions](https://github.com/features/actions). 131 | 132 | ## 🚀 Motivation 133 | 134 | This project aims to enhance the usability of PyBaMM for both newcomers and experienced users alike by providing standardised templates that incorporate best practices and automation tools. The `pybamm-cookie` template is set to lower the barrier to battery modeling, making it easier for the research community to adopt PyBaMM for their battery modeling projects. The project also supports model entry points and parameter set entry points, allowing community contributors to create and share models/parameter sets of their repositories using the copier template without directly adding them upstream. This lets community contributors retain ownership and choose license terms and also grants flexibility to the PyBaMM team in supporting models. Support for all of GitHub’s functionality and infrastructure is contained within the template. 135 | 136 | ## 🛠️ Contributing to `pybamm-cookie` 137 | 138 | If you'd like to help us develop `pybamm-cookie` by improving the template's features, writing documentation, or fixing embarrassing bugs, please have a look at these [guidelines](https://github.com/pybamm-team/pybamm-cookie/blob/main/CONTRIBUTING.md). 139 | 140 | ## 📫 Get in touch 141 | 142 | For any questions, comments, suggestions or bug reports, please see the 143 | [contact page](https://www.pybamm.org/community). 144 | 145 | ## 📃 License 146 | 147 | The `pybamm-cookie` project is open source code. For more information about its license, see [LICENSE](https://github.com/pybamm-team/pybamm-cookie/blob/main/LICENSE). 148 | 149 | ## ✨ Credits 150 | This project is highly inspired by these two projects - 151 | - [SciCookie](https://github.com/osl-incubator/scicookie), a cookiecutter template developed by [Open Science Labs](https://opensciencelabs.org/) to provide a boilerplate to generate Python based projects with a hassle free experience. 152 | - [scientific-python/cookie](https://github.com/scientific-python/cookie), a project that supports copier/cookiecutter/cruft template generation for new Python projects based on Scientific Python developer guide. 153 | 154 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/models/input/SPM.py: -------------------------------------------------------------------------------- 1 | """ 2 | This code is adopted from the PyBaMM project under the BSD-3-Clause 3 | 4 | Copyright (c) 2018-2024, the PyBaMM team. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | """ 32 | 33 | 34 | # 35 | # Basic Single Particle Model (SPM) 36 | # 37 | import pybamm 38 | 39 | 40 | class SPM(pybamm.lithium_ion.BaseModel): 41 | """Single Particle Model (SPM) model of a lithium-ion battery, from 42 | :footcite:t:`Marquis2019`. 43 | 44 | This class differs from the :class:`pybamm.lithium_ion.SPM` model class in that it 45 | shows the whole model in a single class. This comes at the cost of flexibility in 46 | combining different physical effects, and in general the main SPM class should be 47 | used instead. 48 | 49 | Parameters 50 | ---------- 51 | name : str, optional 52 | The name of the model. 53 | """ 54 | 55 | def __init__(self, name="Single Particle Model"): 56 | super().__init__({}, name) 57 | pybamm.citations.register("Marquis2019") 58 | # `param` is a class containing all the relevant parameters and functions for 59 | # this model. These are purely symbolic at this stage, and will be set by the 60 | # `ParameterValues` class when the model is processed. 61 | param = self.param 62 | 63 | ###################### 64 | # Variables 65 | ###################### 66 | # Variables that depend on time only are created without a domain 67 | Q = pybamm.Variable("Discharge capacity [A.h]") 68 | # Variables that vary spatially are created with a domain 69 | c_s_n = pybamm.Variable( 70 | "X-averaged negative particle concentration [mol.m-3]", 71 | domain="negative particle", 72 | ) 73 | c_s_p = pybamm.Variable( 74 | "X-averaged positive particle concentration [mol.m-3]", 75 | domain="positive particle", 76 | ) 77 | 78 | # Constant temperature 79 | T = param.T_init 80 | 81 | ###################### 82 | # Other set-up 83 | ###################### 84 | 85 | # Current density 86 | i_cell = param.current_density_with_time 87 | a_n = 3 * param.n.prim.epsilon_s_av / param.n.prim.R_typ 88 | a_p = 3 * param.p.prim.epsilon_s_av / param.p.prim.R_typ 89 | j_n = i_cell / (param.n.L * a_n) 90 | j_p = -i_cell / (param.p.L * a_p) 91 | 92 | ###################### 93 | # State of Charge 94 | ###################### 95 | I = param.current_with_time 96 | # The `rhs` dictionary contains differential equations, with the key being the 97 | # variable in the d/dt 98 | self.rhs[Q] = I / 3600 99 | # Initial conditions must be provided for the ODEs 100 | self.initial_conditions[Q] = pybamm.Scalar(0) 101 | 102 | ###################### 103 | # Particles 104 | ###################### 105 | 106 | # The div and grad operators will be converted to the appropriate matrix 107 | # multiplication at the discretisation stage 108 | N_s_n = -param.n.prim.D(c_s_n, T) * pybamm.grad(c_s_n) 109 | N_s_p = -param.p.prim.D(c_s_p, T) * pybamm.grad(c_s_p) 110 | self.rhs[c_s_n] = -pybamm.div(N_s_n) 111 | self.rhs[c_s_p] = -pybamm.div(N_s_p) 112 | # Surf takes the surface value of a variable, i.e. its boundary value on the 113 | # right side. This is also accessible via `boundary_value(x, "right")`, with 114 | # "left" providing the boundary value of the left side 115 | c_s_surf_n = pybamm.surf(c_s_n) 116 | c_s_surf_p = pybamm.surf(c_s_p) 117 | # Boundary conditions must be provided for equations with spatial derivatives 118 | self.boundary_conditions[c_s_n] = { 119 | "left": (pybamm.Scalar(0), "Neumann"), 120 | "right": ( 121 | -j_n / (param.F * pybamm.surf(param.n.prim.D(c_s_n, T))), 122 | "Neumann", 123 | ), 124 | } 125 | self.boundary_conditions[c_s_p] = { 126 | "left": (pybamm.Scalar(0), "Neumann"), 127 | "right": ( 128 | -j_p / (param.F * pybamm.surf(param.p.prim.D(c_s_p, T))), 129 | "Neumann", 130 | ), 131 | } 132 | # c_n_init and c_p_init are functions of r and x, but for the SPM we 133 | # take the x-averaged value since there is no x-dependence in the particles 134 | self.initial_conditions[c_s_n] = pybamm.x_average(param.n.prim.c_init) 135 | self.initial_conditions[c_s_p] = pybamm.x_average(param.p.prim.c_init) 136 | # Events specify points at which a solution should terminate 137 | sto_surf_n = c_s_surf_n / param.n.prim.c_max 138 | sto_surf_p = c_s_surf_p / param.p.prim.c_max 139 | self.events += [ 140 | pybamm.Event( 141 | "Minimum negative particle surface stoichiometry", 142 | pybamm.min(sto_surf_n) - 0.01, 143 | ), 144 | pybamm.Event( 145 | "Maximum negative particle surface stoichiometry", 146 | (1 - 0.01) - pybamm.max(sto_surf_n), 147 | ), 148 | pybamm.Event( 149 | "Minimum positive particle surface stoichiometry", 150 | pybamm.min(sto_surf_p) - 0.01, 151 | ), 152 | pybamm.Event( 153 | "Maximum positive particle surface stoichiometry", 154 | (1 - 0.01) - pybamm.max(sto_surf_p), 155 | ), 156 | ] 157 | 158 | # Note that the SPM does not have any algebraic equations, so the `algebraic` 159 | # dictionary remains empty 160 | 161 | ###################### 162 | # (Some) variables 163 | ###################### 164 | # Interfacial reactions 165 | RT_F = param.R * T / param.F 166 | j0_n = param.n.prim.j0(param.c_e_init_av, c_s_surf_n, T) 167 | j0_p = param.p.prim.j0(param.c_e_init_av, c_s_surf_p, T) 168 | eta_n = (2 / param.n.prim.ne) * RT_F * pybamm.arcsinh(j_n / (2 * j0_n)) 169 | eta_p = (2 / param.p.prim.ne) * RT_F * pybamm.arcsinh(j_p / (2 * j0_p)) 170 | phi_s_n = 0 171 | phi_e = -eta_n - param.n.prim.U(sto_surf_n, T) 172 | phi_s_p = eta_p + phi_e + param.p.prim.U(sto_surf_p, T) 173 | V = phi_s_p 174 | num_cells = pybamm.Parameter( 175 | "Number of cells connected in series to make a battery" 176 | ) 177 | 178 | whole_cell = ["negative electrode", "separator", "positive electrode"] 179 | # The `variables` dictionary contains all variables that might be useful for 180 | # visualising the solution of the model 181 | # Primary broadcasts are used to broadcast scalar quantities across a domain 182 | # into a vector of the right shape, for multiplying with other vectors 183 | self.variables = { 184 | "Time [s]": pybamm.t, 185 | "Discharge capacity [A.h]": Q, 186 | "X-averaged negative particle concentration [mol.m-3]": c_s_n, 187 | "Negative particle surface " 188 | "concentration [mol.m-3]": pybamm.PrimaryBroadcast( 189 | c_s_surf_n, "negative electrode" 190 | ), 191 | "Electrolyte concentration [mol.m-3]": pybamm.PrimaryBroadcast( 192 | param.c_e_init_av, whole_cell 193 | ), 194 | "X-averaged positive particle concentration [mol.m-3]": c_s_p, 195 | "Positive particle surface " 196 | "concentration [mol.m-3]": pybamm.PrimaryBroadcast( 197 | c_s_surf_p, "positive electrode" 198 | ), 199 | "Current [A]": I, 200 | "Current variable [A]": I, # for compatibility with pybamm.Experiment 201 | "Negative electrode potential [V]": pybamm.PrimaryBroadcast( 202 | phi_s_n, "negative electrode" 203 | ), 204 | "Electrolyte potential [V]": pybamm.PrimaryBroadcast(phi_e, whole_cell), 205 | "Positive electrode potential [V]": pybamm.PrimaryBroadcast( 206 | phi_s_p, "positive electrode" 207 | ), 208 | "Voltage [V]": V, 209 | "Battery voltage [V]": V * num_cells, 210 | } 211 | # Events specify points at which a solution should terminate 212 | self.events += [ 213 | pybamm.Event("Minimum voltage [V]", V - param.voltage_low_cut), 214 | pybamm.Event("Maximum voltage [V]", param.voltage_high_cut - V), 215 | ] 216 | -------------------------------------------------------------------------------- /template/{{ project_name }}/{% if license=='Apache' %}LICENSE{% endif %}.jinja: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright {% now 'utc', '%Y' %} {{ full_name }} 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /template/{{ project_name }}/src/{{project_slug}}/parameters/input/Chen2020.py: -------------------------------------------------------------------------------- 1 | """ 2 | This code is adopted from the PyBaMM project under the BSD-3-Clause 3 | 4 | Copyright (c) 2018-2024, the PyBaMM team. 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | """ 32 | 33 | 34 | from __future__ import annotations 35 | 36 | import numpy as np 37 | import pybamm 38 | 39 | 40 | def graphite_LGM50_ocp_Chen2020(sto): 41 | """ 42 | LG M50 Graphite open-circuit potential as a function of stochiometry, fit taken 43 | from [1]. 44 | 45 | References 46 | ---------- 47 | .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. 48 | Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for 49 | Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the 50 | Electrochemical Society 167 (2020): 080534. 51 | 52 | Parameters 53 | ---------- 54 | sto: :class:`pybamm.Symbol` 55 | Electrode stochiometry 56 | 57 | Returns 58 | ------- 59 | :class:`pybamm.Symbol` 60 | Open-circuit potential 61 | """ 62 | 63 | u_eq = ( 64 | 1.9793 * np.exp(-39.3631 * sto) 65 | + 0.2482 66 | - 0.0909 * np.tanh(29.8538 * (sto - 0.1234)) 67 | - 0.04478 * np.tanh(14.9159 * (sto - 0.2769)) 68 | - 0.0205 * np.tanh(30.4444 * (sto - 0.6103)) 69 | ) 70 | 71 | return u_eq 72 | 73 | 74 | def graphite_LGM50_electrolyte_exchange_current_density_Chen2020( 75 | c_e, c_s_surf, c_s_max, T 76 | ): 77 | """ 78 | Exchange-current density for Butler-Volmer reactions between graphite and LiPF6 in 79 | EC:DMC. 80 | 81 | References 82 | ---------- 83 | .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. 84 | Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for 85 | Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the 86 | Electrochemical Society 167 (2020): 080534. 87 | 88 | Parameters 89 | ---------- 90 | c_e : :class:`pybamm.Symbol` 91 | Electrolyte concentration [mol.m-3] 92 | c_s_surf : :class:`pybamm.Symbol` 93 | Particle concentration [mol.m-3] 94 | c_s_max : :class:`pybamm.Symbol` 95 | Maximum particle concentration [mol.m-3] 96 | T : :class:`pybamm.Symbol` 97 | Temperature [K] 98 | 99 | Returns 100 | ------- 101 | :class:`pybamm.Symbol` 102 | Exchange-current density [A.m-2] 103 | """ 104 | m_ref = 6.48e-7 # (A/m2)(m3/mol)**1.5 - includes ref concentrations 105 | E_r = 35000 106 | arrhenius = np.exp(E_r / pybamm.constants.R * (1 / 298.15 - 1 / T)) 107 | 108 | return m_ref * arrhenius * c_e**0.5 * c_s_surf**0.5 * (c_s_max - c_s_surf) ** 0.5 109 | 110 | 111 | def nmc_LGM50_ocp_Chen2020(sto): 112 | """ 113 | LG M50 NMC open-circuit potential as a function of stochiometry, fit taken 114 | from [1]. 115 | 116 | References 117 | ---------- 118 | .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. 119 | Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for 120 | Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the 121 | Electrochemical Society 167 (2020): 080534. 122 | 123 | Parameters 124 | ---------- 125 | sto: :class:`pybamm.Symbol` 126 | Electrode stochiometry 127 | 128 | Returns 129 | ------- 130 | :class:`pybamm.Symbol` 131 | Open-circuit potential 132 | """ 133 | 134 | u_eq = ( 135 | -0.8090 * sto 136 | + 4.4875 137 | - 0.0428 * np.tanh(18.5138 * (sto - 0.5542)) 138 | - 17.7326 * np.tanh(15.7890 * (sto - 0.3117)) 139 | + 17.5842 * np.tanh(15.9308 * (sto - 0.3120)) 140 | ) 141 | 142 | return u_eq 143 | 144 | 145 | def nmc_LGM50_electrolyte_exchange_current_density_Chen2020(c_e, c_s_surf, c_s_max, T): 146 | """ 147 | Exchange-current density for Butler-Volmer reactions between NMC and LiPF6 in 148 | EC:DMC. 149 | 150 | References 151 | ---------- 152 | .. [1] Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. 153 | Dhammika Widanage, and Emma Kendrick. "Development of Experimental Techniques for 154 | Parameterization of Multi-scale Lithium-ion Battery Models." Journal of the 155 | Electrochemical Society 167 (2020): 080534. 156 | 157 | Parameters 158 | ---------- 159 | c_e : :class:`pybamm.Symbol` 160 | Electrolyte concentration [mol.m-3] 161 | c_s_surf : :class:`pybamm.Symbol` 162 | Particle concentration [mol.m-3] 163 | c_s_max : :class:`pybamm.Symbol` 164 | Maximum particle concentration [mol.m-3] 165 | T : :class:`pybamm.Symbol` 166 | Temperature [K] 167 | 168 | Returns 169 | ------- 170 | :class:`pybamm.Symbol` 171 | Exchange-current density [A.m-2] 172 | """ 173 | m_ref = 3.42e-6 # (A/m2)(m3/mol)**1.5 - includes ref concentrations 174 | E_r = 17800 175 | arrhenius = np.exp(E_r / pybamm.constants.R * (1 / 298.15 - 1 / T)) 176 | 177 | return m_ref * arrhenius * c_e**0.5 * c_s_surf**0.5 * (c_s_max - c_s_surf) ** 0.5 178 | 179 | 180 | def electrolyte_diffusivity_Nyman2008(c_e, T): 181 | """ 182 | Diffusivity of LiPF6 in EC:EMC (3:7) as a function of ion concentration. The data 183 | comes from [1] 184 | 185 | References 186 | ---------- 187 | .. [1] A. Nyman, M. Behm, and G. Lindbergh, "Electrochemical characterisation and 188 | modelling of the mass transport phenomena in LiPF6-EC-EMC electrolyte," 189 | Electrochim. Acta, vol. 53, no. 22, pp. 6356–6365, 2008. 190 | 191 | Parameters 192 | ---------- 193 | c_e: :class:`pybamm.Symbol` 194 | Dimensional electrolyte concentration 195 | T: :class:`pybamm.Symbol` 196 | Dimensional temperature 197 | 198 | Returns 199 | ------- 200 | :class:`pybamm.Symbol` 201 | Solid diffusivity 202 | """ 203 | 204 | D_c_e = 8.794e-11 * (c_e / 1000) ** 2 - 3.972e-10 * (c_e / 1000) + 4.862e-10 205 | 206 | # Nyman et al. (2008) does not provide temperature dependence 207 | 208 | return D_c_e 209 | 210 | 211 | def electrolyte_conductivity_Nyman2008(c_e, T): 212 | """ 213 | Conductivity of LiPF6 in EC:EMC (3:7) as a function of ion concentration. The data 214 | comes from [1]. 215 | 216 | References 217 | ---------- 218 | .. [1] A. Nyman, M. Behm, and G. Lindbergh, "Electrochemical characterisation and 219 | modelling of the mass transport phenomena in LiPF6-EC-EMC electrolyte," 220 | Electrochim. Acta, vol. 53, no. 22, pp. 6356–6365, 2008. 221 | 222 | Parameters 223 | ---------- 224 | c_e: :class:`pybamm.Symbol` 225 | Dimensional electrolyte concentration 226 | T: :class:`pybamm.Symbol` 227 | Dimensional temperature 228 | 229 | Returns 230 | ------- 231 | :class:`pybamm.Symbol` 232 | Solid diffusivity 233 | """ 234 | 235 | sigma_e = ( 236 | 0.1297 * (c_e / 1000) ** 3 - 2.51 * (c_e / 1000) ** 1.5 + 3.329 * (c_e / 1000) 237 | ) 238 | 239 | # Nyman et al. (2008) does not provide temperature dependence 240 | 241 | return sigma_e 242 | 243 | 244 | # Call dict via a function to avoid errors when editing in place 245 | def get_parameter_values(): 246 | """ 247 | Parameters for an LG M50 cell, from the paper :footcite:t:`Chen2020` and references 248 | therein. 249 | 250 | SEI parameters are example parameters for SEI growth from the papers 251 | :footcite:t:`Ramadass2004`, :footcite:t:`ploehn2004solvent`, 252 | :footcite:t:`single2018identifying`, :footcite:t:`safari2008multimodal`, and 253 | :footcite:t:`Yang2017` 254 | 255 | .. note:: 256 | This parameter set does not claim to be representative of the true parameter 257 | values. Instead these are parameter values that were used to fit SEI models to 258 | observed experimental data in the referenced papers. 259 | """ 260 | 261 | return { 262 | "chemistry": "lithium_ion", 263 | # sei 264 | "Ratio of lithium moles to SEI moles": 2.0, 265 | "Inner SEI reaction proportion": 0.5, 266 | "Inner SEI partial molar volume [m3.mol-1]": 9.585e-05, 267 | "Outer SEI partial molar volume [m3.mol-1]": 9.585e-05, 268 | "SEI reaction exchange current density [A.m-2]": 1.5e-07, 269 | "SEI resistivity [Ohm.m]": 200000.0, 270 | "Outer SEI solvent diffusivity [m2.s-1]": 2.5000000000000002e-22, 271 | "Bulk solvent concentration [mol.m-3]": 2636.0, 272 | "Inner SEI open-circuit potential [V]": 0.1, 273 | "Outer SEI open-circuit potential [V]": 0.8, 274 | "Inner SEI electron conductivity [S.m-1]": 8.95e-14, 275 | "Inner SEI lithium interstitial diffusivity [m2.s-1]": 1e-20, 276 | "Lithium interstitial reference concentration [mol.m-3]": 15.0, 277 | "Initial inner SEI thickness [m]": 2.5e-09, 278 | "Initial outer SEI thickness [m]": 2.5e-09, 279 | "EC initial concentration in electrolyte [mol.m-3]": 4541.0, 280 | "EC diffusivity [m2.s-1]": 2e-18, 281 | "SEI kinetic rate constant [m.s-1]": 1e-12, 282 | "SEI open-circuit potential [V]": 0.4, 283 | "SEI growth activation energy [J.mol-1]": 0.0, 284 | "Negative electrode reaction-driven LAM factor [m3.mol-1]": 0.0, 285 | "Positive electrode reaction-driven LAM factor [m3.mol-1]": 0.0, 286 | # cell 287 | "Negative current collector thickness [m]": 1.2e-05, 288 | "Negative electrode thickness [m]": 8.52e-05, 289 | "Separator thickness [m]": 1.2e-05, 290 | "Positive electrode thickness [m]": 7.56e-05, 291 | "Positive current collector thickness [m]": 1.6e-05, 292 | "Electrode height [m]": 0.065, 293 | "Electrode width [m]": 1.58, 294 | "Cell cooling surface area [m2]": 0.00531, 295 | "Cell volume [m3]": 2.42e-05, 296 | "Cell thermal expansion coefficient [m.K-1]": 1.1e-06, 297 | "Negative current collector conductivity [S.m-1]": 58411000.0, 298 | "Positive current collector conductivity [S.m-1]": 36914000.0, 299 | "Negative current collector density [kg.m-3]": 8960.0, 300 | "Positive current collector density [kg.m-3]": 2700.0, 301 | "Negative current collector specific heat capacity [J.kg-1.K-1]": 385.0, 302 | "Positive current collector specific heat capacity [J.kg-1.K-1]": 897.0, 303 | "Negative current collector thermal conductivity [W.m-1.K-1]": 401.0, 304 | "Positive current collector thermal conductivity [W.m-1.K-1]": 237.0, 305 | "Nominal cell capacity [A.h]": 5.0, 306 | "Current function [A]": 5.0, 307 | "Contact resistance [Ohm]": 0, 308 | # negative electrode 309 | "Negative electrode conductivity [S.m-1]": 215.0, 310 | "Maximum concentration in negative electrode [mol.m-3]": 33133.0, 311 | "Negative particle diffusivity [m2.s-1]": 3.3e-14, 312 | "Negative electrode OCP [V]": graphite_LGM50_ocp_Chen2020, 313 | "Negative electrode porosity": 0.25, 314 | "Negative electrode active material volume fraction": 0.75, 315 | "Negative particle radius [m]": 5.86e-06, 316 | "Negative electrode Bruggeman coefficient (electrolyte)": 1.5, 317 | "Negative electrode Bruggeman coefficient (electrode)": 0, 318 | "Negative electrode charge transfer coefficient": 0.5, 319 | "Negative electrode double-layer capacity [F.m-2]": 0.2, 320 | "Negative electrode exchange-current density [A.m-2]" 321 | "": graphite_LGM50_electrolyte_exchange_current_density_Chen2020, 322 | "Negative electrode density [kg.m-3]": 1657.0, 323 | "Negative electrode specific heat capacity [J.kg-1.K-1]": 700.0, 324 | "Negative electrode thermal conductivity [W.m-1.K-1]": 1.7, 325 | "Negative electrode OCP entropic change [V.K-1]": 0.0, 326 | # positive electrode 327 | "Positive electrode conductivity [S.m-1]": 0.18, 328 | "Maximum concentration in positive electrode [mol.m-3]": 63104.0, 329 | "Positive particle diffusivity [m2.s-1]": 4e-15, 330 | "Positive electrode OCP [V]": nmc_LGM50_ocp_Chen2020, 331 | "Positive electrode porosity": 0.335, 332 | "Positive electrode active material volume fraction": 0.665, 333 | "Positive particle radius [m]": 5.22e-06, 334 | "Positive electrode Bruggeman coefficient (electrolyte)": 1.5, 335 | "Positive electrode Bruggeman coefficient (electrode)": 0, 336 | "Positive electrode charge transfer coefficient": 0.5, 337 | "Positive electrode double-layer capacity [F.m-2]": 0.2, 338 | "Positive electrode exchange-current density [A.m-2]" 339 | "": nmc_LGM50_electrolyte_exchange_current_density_Chen2020, 340 | "Positive electrode density [kg.m-3]": 3262.0, 341 | "Positive electrode specific heat capacity [J.kg-1.K-1]": 700.0, 342 | "Positive electrode thermal conductivity [W.m-1.K-1]": 2.1, 343 | "Positive electrode OCP entropic change [V.K-1]": 0.0, 344 | # separator 345 | "Separator porosity": 0.47, 346 | "Separator Bruggeman coefficient (electrolyte)": 1.5, 347 | "Separator density [kg.m-3]": 397.0, 348 | "Separator specific heat capacity [J.kg-1.K-1]": 700.0, 349 | "Separator thermal conductivity [W.m-1.K-1]": 0.16, 350 | # electrolyte 351 | "Initial concentration in electrolyte [mol.m-3]": 1000.0, 352 | "Cation transference number": 0.2594, 353 | "Thermodynamic factor": 1.0, 354 | "Electrolyte diffusivity [m2.s-1]": electrolyte_diffusivity_Nyman2008, 355 | "Electrolyte conductivity [S.m-1]": electrolyte_conductivity_Nyman2008, 356 | # experiment 357 | "Reference temperature [K]": 298.15, 358 | "Total heat transfer coefficient [W.m-2.K-1]": 10.0, 359 | "Ambient temperature [K]": 298.15, 360 | "Number of electrodes connected in parallel to make a cell": 1.0, 361 | "Number of cells connected in series to make a battery": 1.0, 362 | "Lower voltage cut-off [V]": 2.5, 363 | "Upper voltage cut-off [V]": 4.2, 364 | "Open-circuit voltage at 0% SOC [V]": 2.5, 365 | "Open-circuit voltage at 100% SOC [V]": 4.2, 366 | "Initial concentration in negative electrode [mol.m-3]": 29866.0, 367 | "Initial concentration in positive electrode [mol.m-3]": 17038.0, 368 | "Initial temperature [K]": 298.15, 369 | # citations 370 | "notcite": ["Chen2020"], 371 | } 372 | --------------------------------------------------------------------------------