diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 8a42442..2c9c4e1 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: true contact_links: - name: I just have a question... - url: https://github.com/ROVI-org/thevenin/discussions + url: https://github.com/NREL/thevenin/discussions about: Join our discussion instead. Search for existing questions, or ask a new one! \ No newline at end of file diff --git a/.github/linters/.codespellrc b/.github/linters/.codespellrc index d98bdda..f31e6b8 100644 --- a/.github/linters/.codespellrc +++ b/.github/linters/.codespellrc @@ -1,3 +1,3 @@ [codespell] -skip = build,docs,images,reports,sphinx,references +skip = build,docs,images,reports,references ignore-words-list = thev diff --git a/.github/linters/.flake8 b/.github/linters/.flake8 index d0149d4..e250167 100644 --- a/.github/linters/.flake8 +++ b/.github/linters/.flake8 @@ -15,4 +15,4 @@ max-line-length = 80 extend-ignore = E121,E122,E126,E127,E128,E131,E201,E202,E226,E241,E731 -exclude = build,docs,sphinx,images,reports +exclude = build,docs,images,reports,references diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 210d579..380450c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,7 +4,7 @@ Please include a summary of the change and which issue is fixed. Please also inc Fixes # (issue) ## Type of change -Please add a line in the relevant section of [CHANGELOG.md](https://github.com/ROVI-org/thevenin/blob/main/CHANGELOG.md) to document the change (include PR #) - note reverse order of PR #s. If necessary, also add to the list of breaking changes. +Please add a line in the relevant section of [CHANGELOG.md](https://github.com/NREL/thevenin/blob/main/CHANGELOG.md) to document the change (include PR #) - note reverse order of PR #s. If necessary, also add to the list of breaking changes. - [ ] New feature (non-breaking change which adds functionality) - [ ] Optimization (back-end change that improves speed/readability/etc.) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 18cd069..b9006f0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,6 +9,7 @@ on: - 'CHANGELOG*' - 'docs/*' - 'images/*' + - 'LICENSE' - '.github/ISSUE_TEMPLATE/*' pull_request: @@ -20,33 +21,38 @@ on: - 'CHANGELOG*' - 'docs/*' - 'images/*' + - 'LICENSE' - '.github/ISSUE_TEMPLATE/*' jobs: lint: name: (Lint ${{ matrix.python-version }}, ${{ matrix.os }}) - runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: ['ubuntu-latest'] - python-version: ['3.12'] + os: [ubuntu-latest] + python-version: ['3.13'] defaults: run: shell: bash -l {0} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup python + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - name: Spell check run: | pip install codespell codespell --config .github/linters/.codespellrc + - name: Code format run: | pip install flake8 @@ -55,34 +61,44 @@ jobs: tests: name: (Test ${{ matrix.python-version }}, ${{ matrix.os }}) - runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: ['ubuntu-latest', 'windows-latest', 'macos-13', 'macos-latest'] - python-version: ['3.9', '3.12'] + os: [macos-13, macos-latest, windows-latest, ubuntu-latest] + python-version: ['3.9', '3.13'] defaults: run: shell: bash -l {0} steps: - - uses: actions/checkout@v4 - - uses: conda-incubator/setup-miniconda@v3 + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup conda/python + uses: conda-incubator/setup-miniconda@v3 with: - activate-environment: 'rovi' - python-version: ${{ matrix.python-version }} - miniconda-version: 'latest' auto-update-conda: true - - name: Conda dependencies - run: conda install scikits_odes_sundials -c conda-forge + miniconda-version: latest + python-version: ${{ matrix.python-version }} + activate-environment: rovi + + - name: Verify environment + run: | + conda info + conda list + - name: Pip dependencies run: pip install . - - name: List packages - run: conda list + + - name: List info + run: | + conda info + conda list + - name: Pytest run: | pip install pytest - pytest + pytest . diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..509b40f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,210 @@ +name: release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+a[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+b[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+rc[0-9]+' + +env: + PACKAGE_NAME: '' + +jobs: + details: + runs-on: ubuntu-latest + outputs: + tag_version: ${{ steps.release.outputs.tag_version }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Extract tag details + id: release + run: | + if [[ "${{ github.ref_type }}" = "tag" ]]; then + TAG_VERSION=${GITHUB_REF#refs/tags/v} + echo "tag_version=$TAG_VERSION" >> "$GITHUB_OUTPUT" + echo "Tag version is $TAG_VERSION" + else + echo "No tag found" + exit 1 + fi + + check-version: + needs: details + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Fetch info from PyPI + run: | + response=$(curl -s https://pypi.org/pypi/${{ env.PACKAGE_NAME }}/json || echo "{}") + latest_pypi_version=$(echo $response | grep -oP '"releases":\{"\K[^"]+' | sort -rV | head -n 1) + if [[ -z "$latest_pypi_version" ]]; then + echo "Package not found on PyPI." + latest_pypi_version="0.0.0" + fi + echo "Latest version on PyPI: $latest_pypi_version" + echo "latest_pypi_version=$latest_pypi_version" >> $GITHUB_ENV + + - name: Compare version against PyPI and exit if not newer + run: | + TAG_VERSION=${{ needs.details.outputs.tag_version }} + PYPI_VERSION=$latest_pypi_version + + TAG_BASE=${TAG_VERSION%%[a-z]} + PYPI_BASE=${PYPI_VERSION%%[a-z]} + + TAG_SUFFIX=${TAG_VERSION#$TAG_BASE} + PYPI_SUFFIX=${PYPI_VERSION#$PYPI_BASE} + + suffix_count=0 + + [[ -n "$TAG_SUFFIX" ]] && ((suffix_count++)) + [[ -n "$PYPI_SUFFIX" ]] && ((suffix_count++)) + + if [[ "$TAG_VERSION" == "$PYPI_VERSION" ]]; then + echo "The tag $TAG_VERSION matches the PyPI version $PYPI_VERSION." + exit 1 + elif [[ "$suffix_count" == 1 && "$TAG_BASE" == "$PYPI_BASE" ]]; then + if [[ -n "$PYPI_SUFFIX" ]]; then + echo "The tag $TAG_VERSION is newer than PyPI $PYPI_VERSION." + else + echo "The tag $TAG_VERSION is older than PyPI $PYPI_VERSION." + exit 1 + fi + else + newest=$(printf "%s\n%s" "$TAG_VERSION" "$PYPI_VERSION" | sort -V | tail -n 1) + if [[ "$TAG_VERSION" == "$newest" ]]; then + echo "The tag $TAG_VERSION is newer than PyPI $PYPI_VERSION." + else + echo "The tag $TAG_VERSION is older than PyPI $PYPI_VERSION." + exit 1 + fi + fi + + - name: Verify tag and pyproject.toml versions match + run: | + python -m pip install --upgrade pip + pip install setuptools numpy cython + + PKG_VERSION=$(python setup.py --version) + TAG_VERSION=${{ needs.details.outputs.tag_version }} + + if [[ "$PKG_VERSION" != "$TAG_VERSION" ]]; then + echo "Version mismatch: setup.py has $PKG_VERSION, but tag is $TAG_VERSION." + exit 1 + else + echo "Package and tag versions match: $PKG_VERSION == $TAG_VERSION." + fi + + build: + name: (build ubuntu-latest, 3.13) + needs: [details, check-version] + runs-on: ubuntu-latest + + defaults: + run: + shell: bash -l {0} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install build + run: pip install build + + - name: Build distributions + run: python -m build + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: builds + path: dist/* + + test: + name: (test ${{ matrix.python-version }}, ${{ matrix.os }}) + needs: build + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: true + matrix: + os: [macos-13, macos-latest, windows-latest, ubuntu-latest] + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] + + defaults: + run: + shell: bash -l {0} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: dist/ + pattern: builds* + merge-multiple: true + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install thevenin + run: pip install dist/*.whl -v + + - name: Pytest + run: | + pip install pytest + pytest ./tests + + pypi-publish: + name: Upload to PyPI + needs: test + runs-on: ubuntu-latest + + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: dist/ + pattern: builds* + merge-multiple: true + + - name: Check files + run: ls dist + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install twine + run: pip install twine + + - name: Check builds and upload to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + run: | + twine check dist/* + twine upload dist/* diff --git a/.gitignore b/.gitignore index 7b994a1..609f600 100644 --- a/.gitignore +++ b/.gitignore @@ -81,8 +81,7 @@ instance/ .scrapy # Sphinx documentation -docs/ -sphinx/ +docs/build # PyBuilder .pybuilder/ diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..22eed41 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,16 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set OS, Python version, and other tools for the build +build: + os: ubuntu-22.04 + tools: + python: latest + +# Location of sphinx configuration file +sphinx: + configuration: docs/source/conf.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 45b3688..9bb1a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,27 @@ # thevenin Changelog -## [Version 0.1.1]() +## [Unreleased](https://github.com/NREL/thevenin) ### New Features ### Optimizations -* Add ``options`` to the ``Experiment.print_steps()`` report. This makes it easier to check solver options for each step. ### Bug Fixes -* Make the final value of ``tspan`` always match ``t_max``. In cases where ``dt`` is used to construct the time array, the final ``dt`` may differ from the one given. Fixes [Issue #10](https://github.com/ROVI-org/thevenin/issues/10). ### Breaking Changes -* Drop support for Python 3.8 which reached end of support as of October 2024. + +## [v1.0.0](https://github.com/NREL/thevenin/tree/v1.0.0) +This is the first official release of `thevenin`. Main features/capabilities are listed below. + +### Features +- Support for any number of RC pairs +- Run constant or dynamic loads with current, voltage, or power control +- Parameters have temperature and state of charge dependence +- Experiment limits to trigger switching between steps +- Multi-limit support (end at voltage, time, etc. - whichever occurs first) + +### Notes +- Implemented `pytest` with full package coverage +- Source/binary distributions available on [PyPI](https://pypi.org/project/thevenin) +- Documentation available on [Read the Docs](https://thevenin.readthedocs.io/) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fde28a4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2024, Alliance for Sustainable Energy, LLC + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..f408970 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +global-exclude tests/* diff --git a/README.md b/README.md index 3342074..0596c60 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ + -
+ # thevenin [![CI][ci-b]][ci-l]   ![tests][test-b]   ![coverage][cov-b]   [![pep8][pep-b]][pep-l] -[ci-b]: https://github.com/ROVI-org/thevenin/actions/workflows/ci.yaml/badge.svg -[ci-l]: https://github.com/ROVI-org/thevenin/actions/workflows/ci.yaml +[ci-b]: https://github.com/NREL/thevenin/actions/workflows/ci.yaml/badge.svg +[ci-l]: https://github.com/NREL/thevenin/actions/workflows/ci.yaml -[test-b]: https://github.com/ROVI-org/thevenin/blob/main/images/tests.svg?raw=true -[cov-b]: https://github.com/ROVI-org/thevenin/blob/main/images/coverage.svg?raw=true +[test-b]: https://github.com/NREL/thevenin/blob/main/images/tests.svg?raw=true +[cov-b]: https://github.com/NREL/thevenin/blob/main/images/coverage.svg?raw=true [pep-b]: https://img.shields.io/badge/code%20style-pep8-orange.svg [pep-l]: https://www.python.org/dev/peps/pep-0008 @@ -24,7 +24,7 @@ This package is a wrapper for the well-known Thevenin equivalent circuit model.

2RC Thevenin circuit. + src="https://github.com/NREL/thevenin/blob/main/images/example_circuit.png?raw=true"/>
Figure 1: 2RC Thevenin circuit.

@@ -57,36 +57,32 @@ The overall cell voltage is V_{\rm cell} = V_{\rm OCV}({\rm SOC}) - \sum_j V_j - IR_0, \end{equation} ``` -where $R_0$ the lone series resistance (Ohm), as shown in Figure 1. Just like the other resistive elements, $R_0$ is a function of SOC and $T_{\rm cell}$. +where $R_0$ is the lone series resistance (Ohm), as shown in Figure 1. Just like the other resistive elements, $R_0$ is a function of SOC and $T_{\rm cell}$. ## Installation -We recommend using [Anaconda](https://anaconda.com) to install this package due to the [scikits-odes-sundials](https://scikits-odes.readthedocs.io) dependency, which is installed separately using `conda install` to avoid having to download and compile SUNDIALS locally. Please refer to the linked `scikits-odes` documentation if you prefer installing without using `conda`. Note that we plan to replace this dependency in a future release to streamline installation. - -After cloning the repository, or downloading the files, use your terminal (MacOS/Linux) or Anaconda Prompt (Windows) to navigate into the folder with the `pyproject.toml` file. Once in the correct folder, execute the following commands: +`thevenin` is installable via either pip or conda. To install from [PyPI](https://pypi.org/project/thevenin) use the following command. ``` -conda create -n rovi python=3.12 scikits_odes_sundials -c conda-forge -conda activate rovi -pip install . +pip install thevenin ``` -The first command creates a new Python environment named `rovi`. The environment will be set up using Python 3.12 and will install the `scikits-odes-sundials` dependency from the `conda-forge` channel. Feel free to use an alternate environment name and/or to specify a different Python version >= 3.9. Although the package supports multiple Python versions, development and testing is primarily done using 3.12. Therefore, if you have issues with another version, you should revert to using 3.12. The last two commands activate your new environment and install `thevenin`. - -If you plan to make changes to the package, you may also want to consider installing in "editable" mode using the `-e` flag, and including the optional developer dependencies, using `[dev]`, as shown below. If you plan to push any changes back into this repository, you should see the [contributing](#contributing) section first. +If you prefer using the `conda` package manager, you can install `thevenin` from the `conda-forge` channel using the command below. ``` -pip install -e .[dev] +conda install -c conda-forge thevenin ``` +If you run into issues with installation due to the [scikit-sundae](https://github.com/NREL/scikit-sundae) dependency, please submit an issue [here](https://github.com/NREL/scikit-sundae/issues). We also manage our own solver package, but distribute it separately. + ## Get Started -The API is organized around three main classes that allow you to construct the model, define an experiment, and interact with the solution. A basic example for a constant-current discharge is given below. To see the documentation for any of the classes or their methods, use Python's built in `help()` function. You can also access the documentation by visiting the [website](https://rovi-org.github.io/thevenin) hosted through GitHub pages. The website includes search functionality and more detailed examples compared to those included in the docstrings. +The API is organized around three main classes that allow you to construct the model, define an experiment, and interact with the solution. A basic example for a constant-current discharge is given below. To learn more about the model and see more detailed examples check out the [documentation](https://thevenin.readthedocs.io/) on Read the Docs. ```python -import thevenin +import thevenin as thev -model = thevenin.Model() +model = thev.Model() -expr = thevenin.Experiment() +expr = thev.Experiment() expr.add_step('current_A', 75., (3600., 1.), limits=('voltage_V', 3.)) soln = model.run(expr) @@ -96,10 +92,28 @@ soln.plot('time_h', 'voltage_V') **Notes:** * If you are new to Python, check out [Spyder IDE](https://www.spyder-ide.org/). Spyder is a powerful interactive development environment (IDE) that can make programming in Python more approachable to new users. -## Contributing -If you'd like to contribute to this package, please look through the existing [issues](https://github.com/ROVI-org/thevenin/issues). If the bug you've caught or the feature you'd like to add isn't already being worked on, please submit a new issue before getting started. You should also read through the [developer guidelines](https://rovi-org.github.io/thevenin/development). +## Citing this Work +This work was authored by researchers at the National Renewable Energy Laboratory (NREL). The project is tracked in NREL's software records under SWR-24-132 and has a DOI available for citing the work. If you use use this package in your work, please include the following citation: -## Acknowledgements -This work was authored by the National Renewable Energy Laboratory (NREL), operated by Alliance for Sustainable Energy, LLC, for the U.S. Department of Energy (DOE). The views expressed in the repository do not necessarily represent the views of the DOE or the U.S. Government. +> Placeholder... waiting for DOI. + +For convenience, we also provide the following for your BibTex: +``` +@misc{Randall2024, + title = {{thevenin: Equivalent circuit models in Python}}, + author = {Randall, Corey R.}, + year = {2024}, + doi = {placeholder... waiting for DOI}, + url = {https://github.com/NREL/thevenin}, +} +``` + +## Acknowledgements The motivation and funding for this project came from the Rapid Operational Validation Initiative (ROVI) sponsored by the Office of Electricity. The focus of ROVI is "to greatly reduce time required for emerging energy storage technologies to go from lab to market by developing new tools that will accelerate the testing and validation process needed to ensure commercial success." If interested, you can read more about ROVI [here](https://www.energy.gov/oe/rapid-operational-validation-initiative-rovi). + +## Contributing +If you'd like to contribute to this package, please look through the existing [issues](https://github.com/NREL/thevenin/issues). If the bug you've caught or the feature you'd like to add isn't already being worked on, please submit a new issue before getting started. You should also read through the [developer guidelines](https://thevenin.readthedocs.io/development). + +## Disclaimer +This work was authored by the National Renewable Energy Laboratory (NREL), operated by Alliance for Sustainable Energy, LLC, for the U.S. Department of Energy (DOE). The views expressed in the repository do not necessarily represent the views of the DOE or the U.S. Government. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/jupyter_execute/0b1e8be199b138c63b6da0d10661b9a7c79fafe232468e58597a48ca0ea07d7e.png b/docs/jupyter_execute/0b1e8be199b138c63b6da0d10661b9a7c79fafe232468e58597a48ca0ea07d7e.png new file mode 100644 index 0000000..98019e4 Binary files /dev/null and b/docs/jupyter_execute/0b1e8be199b138c63b6da0d10661b9a7c79fafe232468e58597a48ca0ea07d7e.png differ diff --git a/docs/jupyter_execute/0e1ac83fa495aaf6166e3c42ffe52b67a80feb137b63b30cf10a104b4ea00dc3.png b/docs/jupyter_execute/0e1ac83fa495aaf6166e3c42ffe52b67a80feb137b63b30cf10a104b4ea00dc3.png new file mode 100644 index 0000000..7e46419 Binary files /dev/null and b/docs/jupyter_execute/0e1ac83fa495aaf6166e3c42ffe52b67a80feb137b63b30cf10a104b4ea00dc3.png differ diff --git a/docs/jupyter_execute/117b26505c6fecdcb9ca03e91a1511f99cf552d54a4da61141586eb2b11118be.png b/docs/jupyter_execute/117b26505c6fecdcb9ca03e91a1511f99cf552d54a4da61141586eb2b11118be.png new file mode 100644 index 0000000..0653d8d Binary files /dev/null and b/docs/jupyter_execute/117b26505c6fecdcb9ca03e91a1511f99cf552d54a4da61141586eb2b11118be.png differ diff --git a/docs/jupyter_execute/263f6c968931a73d6ef666a726975503ac36ddb568acd9ed226ad2f8679a0742.png b/docs/jupyter_execute/263f6c968931a73d6ef666a726975503ac36ddb568acd9ed226ad2f8679a0742.png new file mode 100644 index 0000000..854f90b Binary files /dev/null and b/docs/jupyter_execute/263f6c968931a73d6ef666a726975503ac36ddb568acd9ed226ad2f8679a0742.png differ diff --git a/docs/jupyter_execute/2909280912fc4238e0932d956c3a4caa9201facc2f89752e26d9fcbde1ba3231.png b/docs/jupyter_execute/2909280912fc4238e0932d956c3a4caa9201facc2f89752e26d9fcbde1ba3231.png new file mode 100644 index 0000000..d08f7d5 Binary files /dev/null and b/docs/jupyter_execute/2909280912fc4238e0932d956c3a4caa9201facc2f89752e26d9fcbde1ba3231.png differ diff --git a/docs/jupyter_execute/3e9b85352be643245b4634f626e01090af302155a1719045e5e95c7324fb817b.png b/docs/jupyter_execute/3e9b85352be643245b4634f626e01090af302155a1719045e5e95c7324fb817b.png new file mode 100644 index 0000000..b82fbe0 Binary files /dev/null and b/docs/jupyter_execute/3e9b85352be643245b4634f626e01090af302155a1719045e5e95c7324fb817b.png differ diff --git a/docs/jupyter_execute/54f31f2b3c189fb3cb30c66acd387c49dcc73f776030b9693e7f66724396a1ec.png b/docs/jupyter_execute/54f31f2b3c189fb3cb30c66acd387c49dcc73f776030b9693e7f66724396a1ec.png new file mode 100644 index 0000000..b300c90 Binary files /dev/null and b/docs/jupyter_execute/54f31f2b3c189fb3cb30c66acd387c49dcc73f776030b9693e7f66724396a1ec.png differ diff --git a/docs/jupyter_execute/5e3f2af20ecd1cc65e59efa847be883aae3634cacf3ba80649702c11ba235731.png b/docs/jupyter_execute/5e3f2af20ecd1cc65e59efa847be883aae3634cacf3ba80649702c11ba235731.png new file mode 100644 index 0000000..f583e33 Binary files /dev/null and b/docs/jupyter_execute/5e3f2af20ecd1cc65e59efa847be883aae3634cacf3ba80649702c11ba235731.png differ diff --git a/docs/jupyter_execute/65618489ca9a793c0652c40fd47d75f2d8f184fbaeff9c9139dec25fcce7d36b.png b/docs/jupyter_execute/65618489ca9a793c0652c40fd47d75f2d8f184fbaeff9c9139dec25fcce7d36b.png new file mode 100644 index 0000000..207a832 Binary files /dev/null and b/docs/jupyter_execute/65618489ca9a793c0652c40fd47d75f2d8f184fbaeff9c9139dec25fcce7d36b.png differ diff --git a/docs/jupyter_execute/67f93fe6bbc1a405dbeca58473b9198a8d1adc53e88119bdcd48aceb9e9b7e3d.png b/docs/jupyter_execute/67f93fe6bbc1a405dbeca58473b9198a8d1adc53e88119bdcd48aceb9e9b7e3d.png new file mode 100644 index 0000000..2c91729 Binary files /dev/null and b/docs/jupyter_execute/67f93fe6bbc1a405dbeca58473b9198a8d1adc53e88119bdcd48aceb9e9b7e3d.png differ diff --git a/docs/jupyter_execute/6e8bb01372ee244a66128a702d9178f02f560b0f69ae348160eedafc71e231f3.png b/docs/jupyter_execute/6e8bb01372ee244a66128a702d9178f02f560b0f69ae348160eedafc71e231f3.png new file mode 100644 index 0000000..03eba96 Binary files /dev/null and b/docs/jupyter_execute/6e8bb01372ee244a66128a702d9178f02f560b0f69ae348160eedafc71e231f3.png differ diff --git a/docs/jupyter_execute/6f6d61c2e2a9e61bde545b17612082e336dbf12657fed44464f81392ef08bcd3.png b/docs/jupyter_execute/6f6d61c2e2a9e61bde545b17612082e336dbf12657fed44464f81392ef08bcd3.png new file mode 100644 index 0000000..5f40d11 Binary files /dev/null and b/docs/jupyter_execute/6f6d61c2e2a9e61bde545b17612082e336dbf12657fed44464f81392ef08bcd3.png differ diff --git a/docs/jupyter_execute/7bdc777046c1c114be028beeaf78b078b852f3f468d81e5de44497baa0098529.png b/docs/jupyter_execute/7bdc777046c1c114be028beeaf78b078b852f3f468d81e5de44497baa0098529.png new file mode 100644 index 0000000..e714ee3 Binary files /dev/null and b/docs/jupyter_execute/7bdc777046c1c114be028beeaf78b078b852f3f468d81e5de44497baa0098529.png differ diff --git a/docs/jupyter_execute/7c8f57f652261b4bf928ccf71909dbf3c0315193407a671f723e581b531ebbfe.png b/docs/jupyter_execute/7c8f57f652261b4bf928ccf71909dbf3c0315193407a671f723e581b531ebbfe.png new file mode 100644 index 0000000..c920fff Binary files /dev/null and b/docs/jupyter_execute/7c8f57f652261b4bf928ccf71909dbf3c0315193407a671f723e581b531ebbfe.png differ diff --git a/docs/jupyter_execute/873548556a50f2ceb43c031c62b56329947da6ab8c37e7e79190a1d53905a422.png b/docs/jupyter_execute/873548556a50f2ceb43c031c62b56329947da6ab8c37e7e79190a1d53905a422.png new file mode 100644 index 0000000..997e779 Binary files /dev/null and b/docs/jupyter_execute/873548556a50f2ceb43c031c62b56329947da6ab8c37e7e79190a1d53905a422.png differ diff --git a/docs/jupyter_execute/87f14a8542a80d94b12c486d2a7c90edabb65eb5f5ad4dd4db4e12fd4b83f1ea.png b/docs/jupyter_execute/87f14a8542a80d94b12c486d2a7c90edabb65eb5f5ad4dd4db4e12fd4b83f1ea.png new file mode 100644 index 0000000..9d90dff Binary files /dev/null and b/docs/jupyter_execute/87f14a8542a80d94b12c486d2a7c90edabb65eb5f5ad4dd4db4e12fd4b83f1ea.png differ diff --git a/docs/jupyter_execute/8db22403485fbe4480d0cc5e13fce4bc93180755628bfd2c02b35bb41cd17f4d.png b/docs/jupyter_execute/8db22403485fbe4480d0cc5e13fce4bc93180755628bfd2c02b35bb41cd17f4d.png new file mode 100644 index 0000000..fc02e27 Binary files /dev/null and b/docs/jupyter_execute/8db22403485fbe4480d0cc5e13fce4bc93180755628bfd2c02b35bb41cd17f4d.png differ diff --git a/docs/jupyter_execute/92a4ae3ce66c5787a093e68727ab74ca41566ea2b8988989bc9e1587d73270c4.png b/docs/jupyter_execute/92a4ae3ce66c5787a093e68727ab74ca41566ea2b8988989bc9e1587d73270c4.png new file mode 100644 index 0000000..699f121 Binary files /dev/null and b/docs/jupyter_execute/92a4ae3ce66c5787a093e68727ab74ca41566ea2b8988989bc9e1587d73270c4.png differ diff --git a/docs/jupyter_execute/946e0a008234eed58f82547ace4186bb50604d73709eb423ec8c42de265920d7.png b/docs/jupyter_execute/946e0a008234eed58f82547ace4186bb50604d73709eb423ec8c42de265920d7.png new file mode 100644 index 0000000..2ed3a74 Binary files /dev/null and b/docs/jupyter_execute/946e0a008234eed58f82547ace4186bb50604d73709eb423ec8c42de265920d7.png differ diff --git a/docs/jupyter_execute/9962d6e14d363f511d12deeffca1622a4e436058c09d5a7c1d307f3fe7032fd3.png b/docs/jupyter_execute/9962d6e14d363f511d12deeffca1622a4e436058c09d5a7c1d307f3fe7032fd3.png new file mode 100644 index 0000000..4a7648f Binary files /dev/null and b/docs/jupyter_execute/9962d6e14d363f511d12deeffca1622a4e436058c09d5a7c1d307f3fe7032fd3.png differ diff --git a/docs/jupyter_execute/a1c914a09baf612351952bef7dab8607f206e4878de799a68b08abcc88b54752.png b/docs/jupyter_execute/a1c914a09baf612351952bef7dab8607f206e4878de799a68b08abcc88b54752.png new file mode 100644 index 0000000..d49d703 Binary files /dev/null and b/docs/jupyter_execute/a1c914a09baf612351952bef7dab8607f206e4878de799a68b08abcc88b54752.png differ diff --git a/docs/jupyter_execute/ace90a46b8d4203d119c06825097951c42852339047cb26f73d78b1637a42f43.png b/docs/jupyter_execute/ace90a46b8d4203d119c06825097951c42852339047cb26f73d78b1637a42f43.png new file mode 100644 index 0000000..5bd68a4 Binary files /dev/null and b/docs/jupyter_execute/ace90a46b8d4203d119c06825097951c42852339047cb26f73d78b1637a42f43.png differ diff --git a/docs/jupyter_execute/b2de80016137565066efde91f82e4ac733749f81d9666401cde53c615dcc27e6.png b/docs/jupyter_execute/b2de80016137565066efde91f82e4ac733749f81d9666401cde53c615dcc27e6.png new file mode 100644 index 0000000..c871735 Binary files /dev/null and b/docs/jupyter_execute/b2de80016137565066efde91f82e4ac733749f81d9666401cde53c615dcc27e6.png differ diff --git a/docs/jupyter_execute/bc4daa5dd807256669b9e876c8786edd57baa6e79efc5663155eb6cbd680f3e3.png b/docs/jupyter_execute/bc4daa5dd807256669b9e876c8786edd57baa6e79efc5663155eb6cbd680f3e3.png new file mode 100644 index 0000000..6d19f84 Binary files /dev/null and b/docs/jupyter_execute/bc4daa5dd807256669b9e876c8786edd57baa6e79efc5663155eb6cbd680f3e3.png differ diff --git a/docs/jupyter_execute/bf30186108bc72343f3c33fecefe9277e36392192a96c309f071cfd5b3eb4d56.png b/docs/jupyter_execute/bf30186108bc72343f3c33fecefe9277e36392192a96c309f071cfd5b3eb4d56.png new file mode 100644 index 0000000..73a2e35 Binary files /dev/null and b/docs/jupyter_execute/bf30186108bc72343f3c33fecefe9277e36392192a96c309f071cfd5b3eb4d56.png differ diff --git a/docs/jupyter_execute/bf45c11afc81258b0d781083c888d4320c194d7c24e20e3cda1174cf5dad03e0.png b/docs/jupyter_execute/bf45c11afc81258b0d781083c888d4320c194d7c24e20e3cda1174cf5dad03e0.png new file mode 100644 index 0000000..62f69de Binary files /dev/null and b/docs/jupyter_execute/bf45c11afc81258b0d781083c888d4320c194d7c24e20e3cda1174cf5dad03e0.png differ diff --git a/docs/jupyter_execute/c030f270f93e1a2e60568ccbb0d223ac0ebff179873593a43800af123871440a.png b/docs/jupyter_execute/c030f270f93e1a2e60568ccbb0d223ac0ebff179873593a43800af123871440a.png new file mode 100644 index 0000000..8913989 Binary files /dev/null and b/docs/jupyter_execute/c030f270f93e1a2e60568ccbb0d223ac0ebff179873593a43800af123871440a.png differ diff --git a/docs/jupyter_execute/c107a6dfd6996b285ed0417049fff7921ecc9fdf04d164a5d38b09c5d79a2928.png b/docs/jupyter_execute/c107a6dfd6996b285ed0417049fff7921ecc9fdf04d164a5d38b09c5d79a2928.png new file mode 100644 index 0000000..3d56743 Binary files /dev/null and b/docs/jupyter_execute/c107a6dfd6996b285ed0417049fff7921ecc9fdf04d164a5d38b09c5d79a2928.png differ diff --git a/docs/jupyter_execute/c4ea032c0195cf3bf932cd7fdd8d3bcc9aa516477d422551c976f54de02de893.png b/docs/jupyter_execute/c4ea032c0195cf3bf932cd7fdd8d3bcc9aa516477d422551c976f54de02de893.png new file mode 100644 index 0000000..0255243 Binary files /dev/null and b/docs/jupyter_execute/c4ea032c0195cf3bf932cd7fdd8d3bcc9aa516477d422551c976f54de02de893.png differ diff --git a/docs/jupyter_execute/cb7009fb438a317d3cf2d2d40f2186223a44510d697b4d96212db8f30220b5b1.png b/docs/jupyter_execute/cb7009fb438a317d3cf2d2d40f2186223a44510d697b4d96212db8f30220b5b1.png new file mode 100644 index 0000000..557e6ec Binary files /dev/null and b/docs/jupyter_execute/cb7009fb438a317d3cf2d2d40f2186223a44510d697b4d96212db8f30220b5b1.png differ diff --git a/docs/jupyter_execute/cdad20abfcc24fbd4cf28786828a3603ff6d4ead6bcb3bc0c18f0b042b8295c2.png b/docs/jupyter_execute/cdad20abfcc24fbd4cf28786828a3603ff6d4ead6bcb3bc0c18f0b042b8295c2.png new file mode 100644 index 0000000..8d1b2c9 Binary files /dev/null and b/docs/jupyter_execute/cdad20abfcc24fbd4cf28786828a3603ff6d4ead6bcb3bc0c18f0b042b8295c2.png differ diff --git a/docs/jupyter_execute/de5e972375fe7cd173b51f678e6e3618ea3e5dccef27d7d271e594eac2d6adec.png b/docs/jupyter_execute/de5e972375fe7cd173b51f678e6e3618ea3e5dccef27d7d271e594eac2d6adec.png new file mode 100644 index 0000000..0686b1d Binary files /dev/null and b/docs/jupyter_execute/de5e972375fe7cd173b51f678e6e3618ea3e5dccef27d7d271e594eac2d6adec.png differ diff --git a/docs/jupyter_execute/examples/dict_inputs.ipynb b/docs/jupyter_execute/examples/dict_inputs.ipynb new file mode 100644 index 0000000..456d640 --- /dev/null +++ b/docs/jupyter_execute/examples/dict_inputs.ipynb @@ -0,0 +1,235 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Dictionary Inputs\n", + "In the previous example, the model parameters were built from a '.yaml' file. In some cases, the functional parameters are relatively complex and can be challenging to specify in the '.yaml' format. Therefore, the model can also be constructed using a dictionary, as demonstrated below.\n", + "\n", + "## Import Modules" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import thevenin as thev" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define the Parameters\n", + "In addition to the open circuit voltage (`ocv`), all circuit elements (i.e., `R0`, `R1`, `C1`, etc.) must be specified as functions. While `OCV` is only a function of the state of charge (`soc`, -), the circuit elements are function of both soc and temperature (`T_cell`, K). It is important that these are the only inputs to the functions and that the inputs are given in the correct order. \n", + "\n", + "The functions below come from fitting the equivalent circuit model to a 75 Ah graphite-NMC battery made by Kokam. Fits were performed using charge and discharge pulses from HPPC tests done at multiple temperatures. The `soc` was assumed constant during a single pulse and each resistor and capacitor element was fit as a constant for a given soc/temperature condition. Expressions below come from AI-Batt, which is an open-source software capable of semi-autonomously identifying algebraic expressions that map inputs (`soc` and `T_cell`) to outputs (`R0`, `R1`, `C1`)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "stressors = {'q_dis': 1.}\n", + "\n", + "\n", + "def calc_xa(soc: float) -> float:\n", + " return 8.5e-3 + soc*(7.8e-1 - 8.5e-3)\n", + "\n", + "\n", + "def calc_Ua(soc: float) -> float:\n", + " xa = calc_xa(soc)\n", + " Ua = 0.6379 + 0.5416*np.exp(-305.5309*xa) \\\n", + " + 0.0440*np.tanh(-1.*(xa-0.1958) / 0.1088) \\\n", + " - 0.1978*np.tanh((xa-1.0571) / 0.0854) \\\n", + " - 0.6875*np.tanh((xa+0.0117) / 0.0529) \\\n", + " - 0.0175*np.tanh((xa-0.5692) / 0.0875)\n", + "\n", + " return Ua\n", + "\n", + "\n", + "def normalize_inputs(soc: float, T_cell: float) -> dict:\n", + " inputs = {\n", + " 'T_norm': T_cell / (273.15 + 35.),\n", + " 'Ua_norm': calc_Ua(soc) / 0.123,\n", + " }\n", + " return inputs\n", + "\n", + "\n", + "def ocv_func(soc: float) -> float:\n", + " coeffs = np.array([\n", + " 1846.82880284425, -9142.89133579961, 19274.3547435787, -22550.631463739,\n", + " 15988.8818738468, -7038.74760241881, 1895.2432152617, -296.104300038221,\n", + " 24.6343726509044, 2.63809042502323,\n", + " ])\n", + " return np.polyval(coeffs, soc)\n", + "\n", + "\n", + "def R0_func(soc: float, T_cell: float) -> float:\n", + " inputs = normalize_inputs(soc, T_cell)\n", + " T_norm = inputs['T_norm']\n", + " Ua_norm = inputs['Ua_norm']\n", + "\n", + " b = np.array([4.07e12, 23.2, -16., -47.5, 2.62])\n", + "\n", + " R0 = b[0] * np.exp( b[1] / T_norm**4 * Ua_norm**(1/4) ) \\\n", + " * np.exp( b[2] / T_norm**4 * Ua_norm**(1/3) ) \\\n", + " * np.exp( b[3] / T_norm**0.5 ) \\\n", + " * np.exp( b[4] / stressors['q_dis'] )\n", + "\n", + " return R0\n", + "\n", + "\n", + "def R1_func(soc: float, T_cell: float) -> float:\n", + " inputs = normalize_inputs(soc, T_cell)\n", + " T_norm = inputs['T_norm']\n", + " Ua_norm = inputs['Ua_norm']\n", + "\n", + " b = np.array([2.84e-5, -12.5, 11.6, 1.96, -1.67])\n", + "\n", + " R1 = b[0] * np.exp( b[1] / T_norm**3 * Ua_norm**(1/4) ) \\\n", + " * np.exp( b[2] / T_norm**4 * Ua_norm**(1/4) ) \\\n", + " * np.exp( b[3] / stressors['q_dis'] ) \\\n", + " * np.exp( b[4] * soc**4 )\n", + "\n", + " return R1\n", + "\n", + "\n", + "def C1_func(soc: float, T_cell: float) -> float:\n", + " inputs = normalize_inputs(soc, T_cell)\n", + " T_norm = inputs['T_norm']\n", + " Ua_norm = inputs['Ua_norm']\n", + "\n", + " b = np.array([19., -3.11, -27., 36.2, -0.256])\n", + "\n", + " C1 = b[0] * np.exp( b[1] * soc**4 ) \\\n", + " * np.exp( b[2] / T_norm**4 * Ua_norm**(1/2) ) \\\n", + " * np.exp( b[3] / T_norm**3 * Ua_norm**(1/3) ) \\\n", + " * np.exp( b[4] / stressors['q_dis']**3 )\n", + "\n", + " return C1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Construct a Model\n", + "The model is constructed below using all necessary keyword arguments. You can see a list of these parameters using ``help(thev.Model)``." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "params = {\n", + " 'num_RC_pairs': 1,\n", + " 'soc0': 1.,\n", + " 'capacity': 75.,\n", + " 'mass': 1.9,\n", + " 'isothermal': False,\n", + " 'Cp': 745.,\n", + " 'T_inf': 300.,\n", + " 'h_therm': 12.,\n", + " 'A_therm': 1.,\n", + " 'ocv': ocv_func,\n", + " 'R0': R0_func,\n", + " 'R1': R1_func,\n", + " 'C1': C1_func,\n", + "}\n", + "\n", + "model = thev.Model(params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build an Experiment\n", + "Experiments are built using the `Experiment` class. An experiment starts out empty and is then constructed by adding a series of current-, voltage-, or power-controlled steps. Each step requires knowing the control mode/units, the control value, a relative time span, and limiting criteria (optional). Control values can be specified as either constants or dynamic profiles with sinatures like `f(t: float) -> float` where `t` is the relative time of the new step, in seconds. The experiment below discharges at a nominal C/5 rate for up to 5 hours. A limit is set such that if the voltage hits 3 V then the next step is triggered early. Afterward, the battery rests for 10 min before charging at C/5 for 5 hours or until 4.2 V is reached. The final step is a 1 hour voltage hold at 4.2 V.\n", + "\n", + "Note that the time span for each step is constructed as `(t_max: float, dt: float)` which is used to determine the time array as `tspan = np.arange(0., t_max + dt, dt)`. You can also construct a time array given `(t_max: float, Nt: int)` by using an integer instead of a float in the second position. In this case, `tspan = np.linspace(0., t_max, Nt)`. To learn more about building an experiment, including which limits are allowed and/or how to adjust solver settings on a per-step basis, see the documentation `help(thev.Experiment)`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 15., (5.*3600., 60.), limits=('voltage_V', 3.))\n", + "expr.add_step('current_A', 0., (600., 5.))\n", + "expr.add_step('current_A', -15., (5.*3600., 60.), limits=('voltage_V', 4.2))\n", + "expr.add_step('voltage_V', 4.2, (3600., 60.))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run the Experiment\n", + "Experiments are run using either the `run` method, as shown below, or the `run_step` method. The difference between the two is that the `run` method will run all experiment steps with one call. If you would prefer to run the discharge first, perform an analysis, and then run the rest, etc. then you will want to use the `run_step` method. In this case, you should always start with step 0 and then run the following steps in order. When you use `run_step` the models internal state is saved at the end of each step. Therefore, after all steps have been run, you should run the `pre` method to pre-process the model back to its original initial state. All of this is handled automatically in the `run` method.\n", + "\n", + "Regardless of how you run your experiment, the return value will be a solution instance. Solution instances each contain a `vars` attribute which contains a dictionary of the output variables. Keys are generally self descriptive and include units where applicable. To quickly plot any two variables against one another, use the `plot` method with the two keys of interest specified for the `x` and `y` variables of the figure. Below, time (in hours) is plotted against voltage." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "soln = model.run(expr)\n", + "soln.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/docs/jupyter_execute/examples/ramping.ipynb b/docs/jupyter_execute/examples/ramping.ipynb new file mode 100644 index 0000000..f8b9a57 --- /dev/null +++ b/docs/jupyter_execute/examples/ramping.ipynb @@ -0,0 +1,236 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Ramping\n", + "Even with robust numerical solvers and thoughtfully chosen default tolerances, simulations may occasionally fail under certain conditions. This is often due to either inconsistent initial conditions or stiffness issues that prevent proper initialization from a rested state. While our solvers are designed to handle many scenarios effectively, the following issues may still arise:\n", + "\n", + "1. **Inconsistent initial conditions:**\n", + " \n", + " Many solvers are capable of detecting and resolving inconsistent initial conditions before taking the first step. However, this feature can be disabled, allowing bad initial conditions to be passed to the solver, and generally resulting in failures.\n", + "\n", + "2. **Stiff problems:**\n", + " \n", + " Some problems are inherently stiff and cannot be initialized effectively, even with a solver's initialization correction schemes. In such cases, the solver may have difficulty determining a stable solution.\n", + "\n", + "To address these issues, introducing a ramped load can stabilize the simulation. By default, `thevenin` models are set to always ask the solver to correct the initial condition. The starting guess that gets passed to the solver is always a rested condition. Therefore, ramped loads can gradually adjust from the initial state to the desired load, making them easier for the solver to handle. This technique helps avoid the solver crashing due to an abrupt change in load.\n", + "\n", + "In this tutorial, we will demonstrate how to use the `loadfns` module to create a ramped load profile. While we will focus one specific function, other useful helper functions are available in the `loadfns` module, and we encourage you to explore the full documentation for more information." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating Ramped Demands\n", + "`thevenin` models supports both constant and dynamic load profiles for each experimental step. For example, below we make a profile that discharges the battery at a constant current until 3.5 V and then charges the battery by ramping the voltage until 4.2 V." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import thevenin as thev\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def voltage_ramp(t: float) -> float:\n", + " return 3.5 + 5e-3*t\n", + "\n", + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75., (3600., 60.), limits=('voltage_V', 3.5))\n", + "expr.add_step('voltage_V', voltage_ramp, (600., 10.), limits=('voltage_V', 4.2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This general approach provides the most flexibility so users can write any constant or dynamic load, including interpolations of data. However, we also provide select loads in the `loadfns` module that help with both solver stability and reduce the amount of code users need to write out for simple profiles. For instance, the same experiment above can also be constructed using the `Ramp` class, as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "voltage_ramp = thev.loadfns.Ramp(5e-3, 3.5)\n", + "\n", + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75., (3600., 60.), limits=('voltage_V', 3.5))\n", + "expr.add_step('voltage_V', voltage_ramp, (600., 10.), limits=('voltage_V', 4.2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below, we demonstrate running this experimental protocol so we can see that it is doing what we expect." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[thevenin UserWarning] Using the default parameter file 'params.yaml'.\n", + "\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "model = thev.Model()\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_min', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stability Ramps\n", + "Aside from a constant ramp, like `Ramp` demonstrated above, ramps are also commonly used to quickly move from a rested state to a constant load. This can help with solver stability over trying to instantaneously pull a load. To build this type of provile, use the `Ramp2Constant` class. Below, we ramp up to a 20 C discharge in one millisecond and then hold the 20 C discharge rate until 3 V." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\crandall\\Documents\\thevenin\\src\\thevenin\\loadfns\\_ramps.py:97: RuntimeWarning: overflow encountered in exp\n", + " sigmoid = 1. / (1. + np.exp(-self._sharpness*(linear - self._step)))\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "dynamic_load = thev.loadfns.Ramp2Constant(20*75/1e-3, 20*75)\n", + "\n", + "expr = thev.Experiment()\n", + "expr.add_step('current_A', dynamic_load, (180., 0.5), limits=('voltage_V', 3.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_s', 'current_A')\n", + "soln.plot('time_s', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These types of \"stability\" ramps become more and more helpful (or needed) as loads become more demanding. They can also depend on the model's parameter set, i.e., for one set of parameters the model may start crashing at a 5 C discharge whereas another set is stable up to 50 C. \n", + "\n", + "## Comparing to Instantaneous Demands\n", + "The default model parameters, and equivalent circuit models in general, is typically fairly stable compared to other higher-fidelity models (e.g., the single particle model or pseudo-2D model). Therefore, here we can also demonstrate that when we run an instantaneous 20 C discharge profile that the results are not significantly impacted. See the figure below that compares the voltage profile above to one obtained without the ramped profile." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75*20, (180., 75), limits=('voltage_V', 3.))\n", + "\n", + "soln2 = model.run(expr)\n", + "\n", + "plt.plot(soln.vars['time_s'], soln.vars['voltage_V'], '-k')\n", + "plt.plot(soln2.vars['time_s'], soln2.vars['voltage_V'], 'ok', markerfacecolor='none')\n", + " \n", + "plt.xlabel('Time [s]');\n", + "plt.ylabel('Voltage [V]');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Due to the ramp the initial conditions are obviously a bit different. However, since the ramp occurs over just one millisecond, the profile from the ramped case (solid line) very quickly adjusts to the same voltage as the case where current is instantaneous (open markers). The solutions maintain good agreement throughout the rest of discharge." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion\n", + "In this tutorial, you’ve seen how ramped loads can stabilize simulations that struggle with abrupt load changes. By using the loadfns module, you can easily implement these profiles, ensuring smoother transitions for the solver. For more advanced load functions, check out the full documentation to optimize your simulations further." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/docs/jupyter_execute/examples/step_functions.ipynb b/docs/jupyter_execute/examples/step_functions.ipynb new file mode 100644 index 0000000..016cc5f --- /dev/null +++ b/docs/jupyter_execute/examples/step_functions.ipynb @@ -0,0 +1,214 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Step Functions\n", + "In many experimental setups, dynamic loads are applied to simulate realistic operating conditions. Experimental platforms often handle these dynamic loads effectively, interpolating between data points if necessary to create smooth profiles. However, while interpolation is a convenient tool, there are situations where it might not be the best approach for simulating system behavior. Therefore, we also supply helper functions to construct step-based load profiles.\n", + "\n", + "## Why not interpolate?\n", + "Interpolating data can introduce a level of artificial smoothness that doesn't always reflect the abrupt changes seen in real-world systems. For example, interpolated loads are often used to ease solver convergence, but they may not capture the behavior of systems that respond rapidly to changes. This is particularly important for systems that exhibit stepwise or discrete changes in load, where instantaneous shifts between levels are more appropriate than a continuous curve.\n", + "\n", + "While writing an interpolation function is typically straightforward—requiring little more than a call to a standard library, the complexity increases when building a function that implements stepwise behavior. A step function requires more careful attention to correctly represent when and where the system load changes instantaneously. Consequently, we provide this functionality within the `loadfns` modeule to reduce the users' burden to have to develop their own. \n", + "\n", + "## Overview\n", + "When dealing with numerical simulations, introducing ramps between load changes can significantly improve the stability of the solver, reducing the risk of failure during abrupt transitions. Sudden, instantaneous changes in load can sometimes cause solvers to struggle, especially with stiff systems, leading to crashes or errors. That’s why `thevenin` offers two classes for defining stepped load profiles: `StepFunction` and `RampedSteps`.\n", + "\n", + "The `StepFunction` class is designed for scenarios where immediate, instantaneous changes in load are appropriate, while the `RampedSteps` class helps transition between steps by applying an interpolation ramps over a specified time interval at the start of each new step. These two approaches cover a wide range of scenarios, from systems that can handle rapid shifts to those that require more stable transitions.\n", + "\n", + "Below, we will cover:\n", + "1. Building load profiles using interpolated data.\n", + "2. Setting up multi-step experiments using for loops.\n", + "3. Using the `StepFunctio` class to create instantaneous stepped loads.\n", + "4. Using the `RampedSteps` class to create stable transitions between load steps.\n", + "\n", + "## Dynamic Experiments\n", + "To create dynamic load profiles, especially for more complex experiments, there are many approaches you can take. The `Experiment` class allows users to pass in any Python `Callable` like `f(t: float) -> float` to control each step. Therefore, if you have data, you can easily interpolate the data to create a load profile, or you can automate the construction of load steps using a for loop. Below we demonstrate both approaches." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[thevenin UserWarning] Using the default parameter file 'params.yaml'.\n", + "\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import thevenin as thev\n", + "import numpy as np\n", + "\n", + "model = thev.Model()\n", + "\n", + "# Fake hour-by-hour load data\n", + "time_s = 3600.*np.array([0., 1., 2., 3., 4., 5.])\n", + "current_A = model.capacity*np.array([0.6, 0.3, -0.5, 0.2, 0.3, -0.1])\n", + "\n", + "# Interpolating the data\n", + "interp = lambda t: np.interp(t, time_s, current_A)\n", + "\n", + "expr = thev.Experiment(max_step=60.)\n", + "expr.add_step('current_A', interp, (3600*6, 60.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_h', 'current_A')\n", + "soln.plot('time_h', 'voltage_V')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the script above, the data represents hour-by-hour constant-current loads, which might represent some stationary storage system. Since the current is constant across each hour, interpolating between points poorly approximates the actual system behavior. However, interpolation might be more relevant for other dynamic systems like electric vehicles, where data is resolved on shorter timescales, such as seconds.\n", + "\n", + "A better approach for modeling constant-step experiments, rather than using interpolation, is to manually construct the steps using a for loop. In the code block below, we demonstrate how to create a new experiment with multiple steps, where each step lasts one hour, and the current is set by the values in the `current_A` array." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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XXw+/fRTeTyec7Y3NTVxt2YAABDRAr6B4RtvvOH7eePGjXK73b51j8ejkpISdenSJaThAAAAQing4jNx4kRJZ+7KPGXKFL99cXFx6tKli5566qmQhgMAAAilgIuP1+uVJHXt2lW7d+9Wenp62EIBAACEQ8DF56yLeXwFAABAJAi6+EhSSUmJSkpKdOTIEd9I0FkrVqwISTAAAIBQC7r4PProo/rP//xP5efnq2PHjjyJHQAARI2gi8+yZcu0atUq3XPPPeHIAwAAEDZB38enublZw4YNC0cWAACAsAq6+Pzbv/2bVq9eHY4sAAAAYRX0R12nTp3S8uXL9dZbbyk3N1dxcXF++xcvXhyycAAAAKEUdPHZt2+fBg4cKEkqLy/328dEZwAAEMmCLj5bt24NRw4AAICwC3qOz1mVlZXauHGjTp48KUmybTtkoQAAAMIh6OLzxRdfaMyYMerVq5duueUWHT58WJI0ffp0PfTQQyEPCAAAECpBF58HH3xQcXFxOnDggFq3bu3bftddd2nDhg0hDQcAABBKQc/x2bRpkzZu3KisrCy/7T179tT//u//hiwYAABAqAU94tPY2Og30nPWsWPHlJCQEJJQAAAA4RB08RkxYoR+/etf+9Yty5LX69WTTz6pm266KaThAAAAQinoj7qefPJJjRkzRnv27FFzc7N++tOf6oMPPtCxY8f097//PRwZAQAAQiLoEZ9+/fpp//79uuGGG3T77bersbFRd9xxh95991117949HBkBAABCIqgRn5aWFk2YMEHLli3TggULwpUJAAAgLIIa8YmLi9O+ffvClQUAACCsgv6o60c/+pFefvnlcGQJmeLiYnXp0kWJiYkaMmSIdu3a5XQkAAAQAYKe3Hz69GmtWLFCb731lvLy8tSmTRu//U4/nX3t2rWaO3euli1bpiFDhmjJkiUaP368Kioq1KFDB0ezAQAAZwVdfMrLyzV48GBJ0v79+/32RcLT2RcvXqwZM2Zo2rRpkqRly5bpL3/5i1asWKH58+f7HdvU1KSmpibfen19/WXNCgAALq+gio/H49Gjjz6q/v37Ky0tLVyZLlpzc7NKS0tVWFjo2+ZyuTR27Fjt2LHjnOOLior06KOPXs6IAADAQUHN8YmJidG4ceNUW1sbpjiX5vPPP5fH41FGRobf9oyMDFVXV59zfGFhoerq6nxL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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Looping over constant steps\n", + "expr = thev.Experiment(max_step=60.)\n", + "for amps in current_A:\n", + " expr.add_step('current_A', amps, (3600, 60.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_h', 'current_A')\n", + "soln.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This loop-based method significantly improves the accuracy of the results in this case. You can see how different the two voltage profiles are when the load profile is applied correctly, instead of using interpolation. This loop-based approach offers the most flexibility and is recommended when users need precise control over each step. For example, using the `add_step` method allows you to add different limits to each step, which can be incorporated into the loop. This level of control is not always possible with other methods.\n", + "\n", + "## Ramped Transitions\n", + "Unlike `StepFunction`, the `RampedSteps` class introduces \"smooth\" transitions between load steps by ramping up or down over a specified time period. This method is especially useful when dealing with stiff systems, where abrupt changes might otherwise cause solver instability. Below we demonstrate this using the same hour-by-hour profile from above. We set the ramp between steps to be just one millisecond so that the transitions are still quick and approximate an instantaneous change. In this case, the added ramps improve the stability and the full simulation is run, as shown in the figure. Overall, the results are nearly identical to the loop-based approach since the ramps are set to occur over such a small time scale. In particular, the main difference is shown in the current profile, where you can briefly see the first ramp (starting from zero current at `t = 0`)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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/e9HVDEAAMglxoz41NbWavr06fr1r3+tjh07HvP59evXa8KECSoqKvJumzp1qrZv3659+/Yd9z6bmppUX1+f8gYAANovI4KP4zi68cYbdcstt2js2LHH/ZqamhpVVlam3OZ+XFNTc9zvmTdvnioqKry3vn37Bls4AADIKZEGn3vuuUeWZaV9e++99/TYY4+poaFBs2fPDvTnz549W3V1dd7brl27Ar1/AACQWyLt8bnrrrt04403pv2aQYMG6ZVXXtH69etVXFyc8rmxY8fquuuu07PPPquqqirV1tamfN79uKqq6rj3XVxcfMx9AgCA9ivS4NOjRw/16NHjhF/36KOP6qc//an38e7duzV16lQtW7ZM48aNkySNHz9e9957r1paWlRYWChJWr16tYYMGaIuXbqE8x8AAACMYsSqrn79+qV8XFpaKkk69dRT1adPH0nStddeq/vuu0/Tpk3T3XffrW3btumRRx7Rww8/nPV6AQBAbjIi+PhRUVGhVatWqbq6WmPGjFH37t01Z84clrIDAACP5TiOE3URuaKurk6dO3fWrl27VF5eHnU5AADAh/r6evXt21f79+9XRUVF2q9tNyM+QWhoaJAklrUDAGCghoaGEwYfRnzasG1bu3fvVllZmSzLCvS+3TTKaNKJca3841r5x7XKDNfLP66Vf2FdK8dx1NDQoN69eysWS79TDyM+bcRiMa9ZOizl5eU8MHziWvnHtfKPa5UZrpd/XCv/wrhWJxrpcRmxczMAAEAQCD4AACBvEHyypLi4WHPnzmWnaB+4Vv5xrfzjWmWG6+Uf18q/XLhWNDcDAIC8wYgPAADIGwQfAACQNwg+AAAgbxB8AABA3iD4ZMHChQs1YMAAlZSUaNy4cXrjjTeiLiknvfbaa7r88svVu3dvWZal//7v/466pJw1b948nX322SorK1PPnj11xRVXaPv27VGXlZOeeOIJjRgxwtswbfz48Vq+fHnUZRnhgQcekGVZmjlzZtSl5Jyf/OQnsiwr5W3o0KFRl5WzPvnkE33ve99Tt27d1KFDB5155pl68803I6mF4BOyZcuWadasWZo7d642b96skSNHaurUqdq7d2/UpeWcxsZGjRw5UgsXLoy6lJy3bt06VVdXa8OGDVq9erVaWlo0ZcoUNTY2Rl1azunTp48eeOABbdq0SW+++aYuvvhiffvb39a7774bdWk5bePGjXryySc1YsSIqEvJWcOGDdOePXu8t//7v/+LuqSctG/fPp1//vkqLCzU8uXL9ec//1kPPfSQunTpEk1BDkJ1zjnnONXV1d7HiUTC6d27tzNv3rwIq8p9kpwXX3wx6jKMsXfvXkeSs27duqhLMUKXLl2cX/7yl1GXkbMaGhqcwYMHO6tXr3a++c1vOnfccUfUJeWcuXPnOiNHjoy6DCPcfffdzgUXXBB1GR5GfELU3NysTZs2afLkyd5tsVhMkydP1vr16yOsDO1NXV2dJKlr164RV5LbEomEXnjhBTU2Nmr8+PFRl5Ozqqur9a1vfSvluQvH+stf/qLevXtr0KBBuu666/TRRx9FXVJO+v3vf6+xY8fq6quvVs+ePXXWWWfpqaeeiqwegk+IPvvsMyUSCVVWVqbcXllZqZqamoiqQntj27Zmzpyp888/X8OHD4+6nJz0zjvvqLS0VMXFxbrlllv04osv6owzzoi6rJz0wgsvaPPmzZo3b17UpeS0cePGaenSpVqxYoWeeOIJffjhh7rwwgvV0NAQdWk554MPPtATTzyhwYMHa+XKlbr11lv1z//8z3r22WcjqYfT2QHDVVdXa9u2bfQXpDFkyBBt2bJFdXV1+s///E/dcMMNWrduHeHnS3bt2qU77rhDq1evVklJSdTl5LRLL73Ue3/EiBEaN26c+vfvr//4j//QtGnTIqws99i2rbFjx+r++++XJJ111lnatm2bFi1apBtuuCHr9TDiE6Lu3bsrHo+rtrY25fba2lpVVVVFVBXakxkzZujll1/W2rVr1adPn6jLyVlFRUU67bTTNGbMGM2bN08jR47UI488EnVZOWfTpk3au3evRo8erYKCAhUUFGjdunV69NFHVVBQoEQiEXWJOatz5846/fTTtXPnzqhLyTm9evU65o+Mb3zjG5FNDRJ8QlRUVKQxY8ZozZo13m22bWvNmjX0F+BrcRxHM2bM0IsvvqhXXnlFAwcOjLoko9i2raampqjLyDmTJk3SO++8oy1btnhvY8eO1XXXXactW7YoHo9HXWLOOnDggN5//3316tUr6lJyzvnnn3/Mdhs7duxQ//79I6mHqa6QzZo1SzfccIPGjh2rc845RwsWLFBjY6NuuummqEvLOQcOHEj5a+nDDz/Uli1b1LVrV/Xr1y/CynJPdXW1nn/+ef3ud79TWVmZ1zNWUVGhDh06RFxdbpk9e7YuvfRS9evXTw0NDXr++ef16quvauXKlVGXlnPKysqO6RPr1KmTunXrRv/Yl/zwhz/U5Zdfrv79+2v37t2aO3eu4vG4vvvd70ZdWs658847dd555+n+++/Xd77zHb3xxhtavHixFi9eHE1BUS8rywePPfaY069fP6eoqMg555xznA0bNkRdUk5au3atI+mYtxtuuCHq0nLO8a6TJOeZZ56JurScc/PNNzv9+/d3ioqKnB49ejiTJk1yVq1aFXVZxmA5+/Fdc801Tq9evZyioiLnlFNOca655hpn586dUZeVs1566SVn+PDhTnFxsTN06FBn8eLFkdViOY7jRBO5AAAAsoseHwAAkDcIPgAAIG8QfAAAQN4g+AAAgLxB8AEAAHmD4AMAAPIGwQcAAOQNgg8AAMgbBB8AOevGG2/UFVdckfWfu3TpUlmWJcuyNHPmTO/2AQMGaMGCBWm/1/2+zp07h1ojgJPDWV0AImFZVtrPz507V4888oii2ly+vLxc27dvV6dOnTL6vj179mjZsmWaO3duSJUB+DoIPgAisWfPHu/9ZcuWac6cOSknOJeWlqq0tDSK0iQdCWZVVVUZf19VVZUqKipCqAhAEJjqAhCJqqoq762iosILGu5baWnpMVNdEydO1O23366ZM2eqS5cuqqys1FNPPaXGxkbddNNNKisr02mnnably5en/Kxt27bp0ksvVWlpqSorK3X99dfrs88+O6m6Dx48qJtvvlllZWXq169fdCdMAzgpBB8ARnn22WfVvXt3vfHGG7r99tt166236uqrr9Z5552nzZs3a8qUKbr++ut18OBBSdL+/ft18cUX66yzztKbb76pFStWqLa2Vt/5zndO6uc/9NBDGjt2rN566y3ddtttuvXWW1NGqgDkNoIPAKOMHDlSP/7xjzV48GDNnj1bJSUl6t69u6ZPn67Bgwdrzpw5+vzzz7V161ZJ0i9+8QudddZZuv/++zV06FCdddZZWrJkidauXasdO3Zk/PMvu+wy3XbbbTrttNN09913q3v37lq7dm3Q/5kAQkKPDwCjjBgxwns/Ho+rW7duOvPMM73bKisrJUl79+6VJL399ttau3btcfuF3n//fZ1++ukn/fPd6Tn3ZwHIfQQfAEYpLCxM+diyrJTb3NVitm1Lkg4cOKDLL79c//Zv/3bMffXq1SuQn+/+LAC5j+ADoF0bPXq0fvvb32rAgAEqKOApD8h39PgAaNeqq6v1xRdf6Lvf/a42btyo999/XytXrtRNN92kRCIRdXkAsozgA6Bd6927t/70pz8pkUhoypQpOvPMMzVz5kx17txZsRhPgUC+sZyotkUFgBy1dOlSzZw5U/v374/k+wGEhz93AOA46urqVFpaqrvvvjuj7ystLdUtt9wSUlUAvi5GfADgSxoaGlRbWytJ6ty5s7p37+77e3fu3CnpyFL7gQMHhlIfgJNH8AEAAHmDqS4AAJA3CD4AACBvEHwAAEDeIPgAAIC8QfABAAB5g+ADAADyBsEHAADkDYIPAADIG/8/UEgWXInUFCEAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Stabilize the solver with ramped steps\n", + "demand = thev.loadfns.RampedSteps(time_s, current_A, 1e-3)\n", + "\n", + "expr = thev.Experiment(max_step=60.)\n", + "expr.add_step('current_A', demand, (3600*6, 60.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_h', 'current_A')\n", + "soln.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While the `RampedSteps` class improves solver stability, it still lacks flexibility for setting limits on each individual step. For instance, you could apply limits to stop the simulation if the voltage goes outside a specific window (e.g., [3, 4.2]), but this would simply end the entire simulation prematurely. In most cases, you wouldn’t want to stop the simulation completely but instead transition to the next step early. To achieve this behavior, you would need to use loops, or alternatively, set up multiple instances of the `RampedSteps` class if you want to transition between groups of steps based on specific limits rather than between individual steps.\n", + "\n", + "In general, if maximum flexibility is needed, more manual setup is required for multi-step experiments. However, if you can work within the limitations of `RampedSteps`, it is a powerful tool for quickly constructing step-like profiles while maintaining some degree of stability.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we explored various methods for constructing dynamic load profiles using the `StepFunction` and `RampedSteps` classes. We’ve shown how both instantaneous steps and ramps between steps can be modeled and discussed the trade-offs between flexibility, stability, and ease of use. While loop-based approaches offer the greatest control, `RampedSteps` provides a simple and effective way to ensure stability in simulations, making it a valuable option for many users. Ultimately, the best method depends on the complexity of the load profile you need and the requirements of your specific experiment or model." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/docs/jupyter_execute/examples/yaml_inputs.ipynb b/docs/jupyter_execute/examples/yaml_inputs.ipynb new file mode 100644 index 0000000..99285d7 --- /dev/null +++ b/docs/jupyter_execute/examples/yaml_inputs.ipynb @@ -0,0 +1,243 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# YAML File Inputs\n", + "This basic example will walk you through understanding the three main classes required to build and exercise equivalent circuit models using this package. The three classes as the `Model`, `Experiment`, and `StepSolution` or `CylceSolution` classes. Models hold parameters associated with defining the battery circuit, experiments list a series of sequential steps that define a test protocol or duty cycle, and the solution classes provide an interface to access, manipulate, and/or plot the solution.\n", + "\n", + "## Import Modules" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import thevenin as thev" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Construct a Model\n", + "The model class can be constructed using either a '.yaml' file or a dictionary that specifies all keyword arguments shown in the documentation (`help(thev.Model)`). A default '.yaml' file is read in when no input is provided. This is simply for convenience to help users get up and going as quickly as possible. However, you should learn how to write your own '.yaml' file or dictionary input if you would like to use this package to its fullest extent. \n", + "\n", + "The '.yaml' format is very similar to building a dictionary in Python. Use the default 'params.yaml' file given below as a template for your own files. Note that the open circuit voltage `ocv` and circuit elements (`R0`, `R1`, and `C1`) must be input as a `Callable` with the correct inputs in the correct order, i.e., `f(soc: float) -> float` for `ocv` and `f(soc: float, T_cell: float) -> float` for all RC elements. The inputs represent the state of charge (`soc`, -) and cell temperature (`T_cell`, K). Resistor and capacitor outputs should be in Ohm and F, respectively. Since '.yaml' files do not natively support python functions, this package uses a custom `!eval` constructor to interpret functional parameters. The `!eval` constructor should be followed by a pipe `|` so that the interpreter does not get confused by the colon in the `lambda` expression. `np` expressions and basic math are also supported when using the `!eval` constructor.\n", + "\n", + "```yaml\n", + "num_RC_pairs: 1\n", + "soc0: 1.\n", + "capacity: 75.\n", + "mass: 1.9\n", + "isothermal: False\n", + "Cp: 745.\n", + "T_inf: 300.\n", + "h_therm: 12.\n", + "A_therm: 1.\n", + "ocv: !eval | \n", + " lambda soc: 84.6*soc**7 - 348.6*soc**6 + 592.3*soc**5 - 534.3*soc**4 \\\n", + " + 275.*soc**3 - 80.3*soc**2 + 12.8*soc + 2.8\n", + "R0: !eval |\n", + " lambda soc, T_cell: 1e-4 + soc/1e5 - T_cell/3e7\n", + "R1: !eval |\n", + " lambda soc, T_cell: 1e-5 + soc/1e5 - T_cell/3e7\n", + "C1: !eval |\n", + " lambda soc, T_cell: 1e4 + soc*1e4 + np.exp(T_cell/300.)\n", + "```\n", + "\n", + "Although this example only uses a single RC pair, `num_RC_pairs` can be as low as 0 and can be as high as $N$. The number of defined `Rj` and `Cj` elements in the '.yaml' file should be consistent with `num_RC_pairs`. For example, if `num_RC_pairs=0` then only `R0` should be defined, with no other resistors or capacitors. However, if `num_RC_pairs=3` then the user should specify `R0`, `R1`, `R2`, `R3`, `C1`, `C2`, and `C3`. Note that the series resistor element `R0` is always included, even when there are no RC pairs. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[thevenin UserWarning] Using the default parameter file 'params.yaml'.\n", + "\n" + ] + } + ], + "source": [ + "model = thev.Model()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When using the default parameters, a warning will always print. This is to ensure the user is running with their preferred inputs. In the case that a user has a file by the same name, the package will take the default as its preference. Be sure to specify the local or absolute path in this case, e.g., `./params.yaml`, or simply rename your file.\n", + "\n", + "## Build an Experiment\n", + "Experiments are built using the `Experiment` class. An experiment starts out empty and is then constructed by adding a series of current-, voltage-, or power-controlled steps. Each step requires knowing the control mode/units, the control value, a relative time span, and limiting criteria (optional). Control values can be specified as either constants or dynamic profiles with sinatures like `f(t: float) -> float` where `t` is the relative time of the new step, in seconds. The experiment below discharges at a nominal 1C rate for up to 1 hour. A limit is set such that if the voltage hits 3 V then the next step is triggered early. Afterward, the battery rests for 10 min before charging at 1C for 1 hours or until 4.3 V is reached. The remaining three steps perform a voltage hold at 4.3 V for 10 min, a constant power profile of 200 W for 1 hour or until 3.8 V is reached, and a sinusoidal voltage load for 10 min centered around 3.8 V.\n", + "\n", + "Note that the time span for each step is constructed as `(t_max: float, dt: float)` which is used to determine the time array as `tspan = np.arange(0., t_max + dt, dt)`. You can also construct a time array given `(t_max: float, Nt: int)` by using an integer instead of a float in the second position. In this case, `tspan = np.linspace(0., t_max, Nt)`. To learn more about building an experiment, including which limits are allowed and/or how to adjust solver settings on a per-step basis, see the documentation `help(thev.Experiment)`." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "dynamic_load = lambda t: 10e-3*np.sin(2.*np.pi*t / 120.) + 3.8\n", + "\n", + "expr = thev.Experiment(max_step=10.)\n", + "expr.add_step('current_A', 75., (3600., 1.), limits=('voltage_V', 3.))\n", + "expr.add_step('current_A', 0., (600., 1.))\n", + "expr.add_step('current_A', -75., (3600., 1.), limits=('voltage_V', 4.3))\n", + "expr.add_step('voltage_V', 4.3, (600., 1.))\n", + "expr.add_step('power_W', 200., (3600., 1.), limits=('voltage_V', 3.8))\n", + "expr.add_step('voltage_V', dynamic_load, (600., 1.))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run the Experiment\n", + "Experiments are run using either the `run` method, as shown below, or the `run_step` method. The difference between the two is that the `run` method will run all experiment steps with one call. If you would prefer to run the discharge first, perform an analysis, and then run the rest, etc. then you will want to use the `run_step` method. In this case, you should always start with step 0 and then run the following steps in order. When you use `run_step` the models internal state is saved at the end of each step. Therefore, after all steps have been run, you should run the `pre` method to pre-process the model back to its original initial state. All of this is handled automatically in the `run` method.\n", + "\n", + "Regardless of how you run your experiment, the return value will be a solution instance. Solution instances each contain a `vars` attribute which contains a dictionary of the output variables. Keys are generally self descriptive and include units where applicable. To quickly plot any two variables against one another, use the `plot` method with the two keys of interest specified for the `x` and `y` variables of the figure. Below, time (in hours) is plotted against voltage." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "sol = model.run(expr)\n", + "sol.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run step-by-step, perform the following." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Run each index, starting with 0\n", + "solns = []\n", + "for i in range(expr.num_steps):\n", + " solns.append(model.run_step(expr, i))\n", + " \n", + "# Re-run the pre-processor in case you'd like to run another experiment\n", + "model.pre()\n", + " \n", + "# Look at the first step solution (i.e., the 1C discharge)\n", + "solns[0].plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you run an experiment step-by-step, you can also manually stitch them together into a `CycleSolution` once you are finished. Alternatively, if you have a `CycleSolution`, you can pull a single `StepSolution` or a subset of the `CycleSolution` using the `get_steps` method. See below for an example." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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5QYAALgVyg0AAHArlBsAAOBWKDc2evfdd9WiRQv5+fmpV69e2rJlyxX3X7Zsmdq3by8/Pz916dJFK1eudFJS57HlmMybN0/9+/dXaGioQkNDNWjQoF89hrWRrb8n5yUkJMhisej22293bEAT2HpMTp8+rUmTJqlp06by9fVV27Zt3e6/H1uPyZtvvql27dqpXr16ioqK0uOPP67i4mInpXWstWvXatiwYWrWrJksFos+++yzX33OmjVr1L17d/n6+qp169ZatGiRw3M6k63H5NNPP9XgwYPVqFEjBQUFKS4uTomJic4J62oMVFtCQoLh4+NjLFy40Pjpp5+MCRMmGCEhIUZ2dvYl9//+++8NT09P45VXXjF2795tTJs2zfD29jaSk5OdnNxxbD0mI0eONN59911jx44dxp49e4wxY8YYwcHBxpEjR5yc3HFsPSbnpaamGhEREUb//v2N4cOHOyesk9h6TEpKSoyePXsaQ4cONdavX2+kpqYaa9asMXbu3Onk5I5j6zFZvHix4evrayxevNhITU01EhMTjaZNmxqPP/64k5M7xsqVK42nn37a+PTTTw1JxooVK664f0pKilG/fn3jiSeeMHbv3m28/fbbhqenp/H11187J7AT2HpMJk+ebLz88svGli1bjP379xtTp041vL29je3btzsnsAuh3NjguuuuMyZNmlT1dUVFhdGsWTNj5syZl9x/xIgRxi233HLBtl69ehkPPfSQQ3M6k63H5JfKy8uNwMBA44MPPnBURKeryTEpLy83+vTpY8yfP98YPXq025UbW4/JnDlzjJiYGKO0tNRZEZ3O1mMyadIk48Ybb7xg2xNPPGH07dvXoTnNUJ0P8v/7v/8zOnXqdMG2e+65x7j55psdmMw81Tkml9KxY0djxowZ9g/k4jgtVU2lpaXatm2bBg0aVLXNw8NDgwYN0saNGy/5nI0bN16wvyTdfPPNl92/tqnJMfmloqIilZWVqUGDBo6K6VQ1PSbPPfecGjdurHHjxjkjplPV5Jh8/vnniouL06RJkxQeHq7OnTvrpZdeUkVFhbNiO1RNjkmfPn20bdu2qlNXKSkpWrlypYYOHeqUzK7G3f++2oPValVBQYHb/H21RZ27cWZN5ebmqqKiQuHh4RdsDw8P1969ey/5nKysrEvun5WV5bCczlSTY/JLU6ZMUbNmzS76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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Stitch the step solutions together\n", + "cycle_soln = thev.CycleSolution(*solns)\n", + "cycle_soln.plot('time_h', 'voltage_V')\n", + "\n", + "# Pull steps 1--3 (inclusive)\n", + "some_steps = cycle_soln.get_steps((1, 3))\n", + "some_steps.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/docs/jupyter_execute/f43d7715048ca9d85cc3f1b23c05426982e075d15965a93852a2a66908fd3e6e.png b/docs/jupyter_execute/f43d7715048ca9d85cc3f1b23c05426982e075d15965a93852a2a66908fd3e6e.png new file mode 100644 index 0000000..10d63da Binary files /dev/null and b/docs/jupyter_execute/f43d7715048ca9d85cc3f1b23c05426982e075d15965a93852a2a66908fd3e6e.png differ diff --git a/docs/jupyter_execute/user_guide/basic_tutorial.ipynb b/docs/jupyter_execute/user_guide/basic_tutorial.ipynb new file mode 100644 index 0000000..8db4397 --- /dev/null +++ b/docs/jupyter_execute/user_guide/basic_tutorial.ipynb @@ -0,0 +1,273 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic Tutorial\n", + "The `thevenin` package is built around three main classes:\n", + "\n", + "1. `Model` - used to construct instances of an equivalent circuit.\n", + "2. `Experiment` - used to define an experimental protocol containing current, voltage, and/or power-controlled steps.\n", + "3. `Solution` - the result object(s) that contain simulation outputs when a particular model runs a particular experiment.\n", + "\n", + "Each of these classes exist at the base package level so they are easily accessible. In this tutorial you will be introduced to each of class through a minimal example. The example will demonstrate a typical workflow for constructing a model, defining an experiment, and interacting with the solution.\n", + "\n", + "## Construct a Model\n", + "The model class is constructed by providing options and parameters that define your circuit. The input can be given as either a dictionary or using a `.yaml` file. If you do not give an input, we include a default parameters file for you to get started. However, it is important that you understand this file and/or its dictionary equivalent so you can modify parameter definitions as necessary later. For more information about constructing model inputs, see the {ref}`examples ` section.\n", + "\n", + "Here, we will start by simply using the default parameters. A warning will print when the default parameters are accessed, but we can ignore it. After initialization, the class can be printed to check all of the constant options/parameters. The model also contains functional parameters, i.e., properties that change as a function of state of charge (soc) and/or temperature. These values are difficult to represent in the printed output so they are not displayed." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model(\n", + " num_RC_pairs=1,\n", + " soc0=1.0,\n", + " capacity=75.0,\n", + " mass=1.9,\n", + " isothermal=False,\n", + " Cp=745.0,\n", + " T_inf=300.0,\n", + " h_therm=12.0,\n", + " A_therm=1.0,\n", + ")\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[thevenin UserWarning] Using the default parameter file 'params.yaml'.\n", + "\n" + ] + } + ], + "source": [ + "import thevenin as thev\n", + "\n", + "model = thev.Model()\n", + "print(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Options and parameters can be changed after initialization by modifying the corresponding attribute. However, if you modify anything after initialization, you should ALWAYS run the preprocessor `pre()` method afterward. This method is run automatically when the class is first initialized, but needs to be run again manually in some cases. One such case is when options and/or parameters are changes. Forgetting to do this will cause the internal state and options to not be self consistent. We demonstrate the correct way to make changes below, by setting the `isothermal` option to `True`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "model.isothermal = True \n", + "model.pre()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define an Experiment\n", + "The model has two methods, `run()` and `run_step()` that correspond to the steps of the `Experiment` class. Similar to how a typical battery cycler would be programmed, an experiment is built by defining a series of sequential steps. Each step has its own mode (current, voltage, or power), value, time span, and limiting criteria.\n", + "\n", + "While we will not cover solver options in this tutorial, you should know that these options exist and are controlled through the `Experiment` class. Options that should be consistent throughout all steps should be set with keyword arguments when the class instance is created. You can also modify solver options at the per-step level (e.g., tighter tolerances) if needed. For more information, see the full documentation.\n", + "\n", + "Below we construct an experiment instance with two simple steps. The first step discharges the battery at a constant current until it reaches 3 V. Afterward, the battery rests for 10 minutes. Note that the sign convention for current and power are such that positive values discharge the cell and negative values charge the cell." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75., (4000., 60.), limits=('voltage_V', 3.))\n", + "expr.add_step('current_A', 0., (600., 60.))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are also control modes available for both voltage and power, and while we do not demonstrate it here, the load value does not need to be constant. By passing in a callable like `f(t) -> float` where `t` is time and the return value is your load at that time, you can also run a dynamic profiles within a step. \n", + "\n", + "Pay attention to two important details in the example above:\n", + "\n", + "1. The `tspan` input (third argument) uses 4000 seconds in the first step even though the current is chosen such that the battery should dischange within an hour. When `limits` is used within a step, and you want to guarantee the limit is actually reached, you will want to pick a time beyond when you expect the limiting event to occur.\n", + "2. The value `60.` in the second position of the `tspan` argument contains a trailing decimal on purpose. When the decimal is present, Python interprets this as a float rather than an integer. The time step behavior is sensitive to this. When a float is passed, the solution is saved in intervals of this value (here, every 60 seconds). If an integer is passed instead, the full timespan is split into that number of times. In otherwords, `dt = tspan[0] / (tspan[1] - 1)`. We recommend always use floats for steps that have limits.\n", + "\n", + "## Run the Simulation\n", + "As mentioned above, the model contains two methods to run an experiment. You can either run the entire series of experiment steps by calling `run()`, or you can run one step at a time by calling `run_step()`. The most important difference between the two is that the model's internal state is changed and saved at the end of each step when using `run_step()` so that it is ready for the following step. Therefore, steps should only ever be run in sequential order, and steps between multiple experiments should not be mixed. For example, to run the above two steps one at a time, run the following code." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "soln_0 = model.run_step(expr, 0)\n", + "soln_1 = model.run_step(expr, 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Indexing starts at zero to be consistent with the Python language. When steps are run one at a time, the output will be a `StepSolution`, which we discuss more below. \n", + "\n", + "It is common to setup multiple experiments that you'd like a model to run and to loop over them. For example, maybe you want to simulate different discharge rates using one experiment per rate. When using the `run()` method, you can do these back-to-back without much thought, however, when using `run_step()`, the `pre()` method should always be called before switching to another experiment. Otherwise, after the first experiment, the internal state will be at `soc = 0` and when the following experiment tries to discharge the cell at a higher rate, the results will not be physical. Likely this will lead to a crash. Therefore, before we demonstrate the `run()` method, we will call `pre()` to reset the model state from the steps run above." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "model.pre()\n", + "\n", + "soln = model.run(expr)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Interacting with Solutions\n", + "Simulation outputs will give one of two solution objects depending on your run mode. A `StepSolution` is returned when you run step by step and a `CycleSolution` is returned when using `run()`. The latter simply stitches together the individual step solutions. Each solution object has numerous attributes to inform the user whether or not their simulation was successful, how long the integrator took, etc. For `CycleSolution` instances, most of these values are lists where each index corresponds to experimental steps with the same indices. For example, below we see that both steps were successful and the total integration time." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "success = [True, True]\n", + "0.041 s\n" + ] + } + ], + "source": [ + "print(f\"success = {soln.success}\")\n", + "print(soln.solvetime)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Most likely, everything else you will need to extract from solutions can be found in the solution's `vars` dictionary. This dictionary contains easy to read names and units for all of the model's outputs. You can always check the keys to this dictionary by printing the solution instance." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CycleSolution(\n", + " solvetime=0.041 s,\n", + " success=[True, True],\n", + " status=[2, 1],\n", + " nfev=[232, 39],\n", + " njev=[34, 23],\n", + " vars=['time_s', 'time_min', 'time_h', 'soc', 'temperature_K', 'voltage_V',\n", + " 'current_A', 'power_W', 'capacity_Ah', 'eta0_V', 'eta1_V'],\n", + ")\n" + ] + } + ], + "source": [ + "print(soln)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "All values in the `vars` dictionary are 1D arrays that provide the values of the named variable at each integrator step. You can plot any two variables against each other using the `plot()` method. For example, to see voltage plotted against time, see below." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAABKkUlEQVR4nO3deVhU9eI/8PfMAMM+gMg+iAiiiCiKC66luGdaZmomarZoVtq1fl76tt4WLLObltfMMi0z3NLMjdQEd1kV3MAFBFnd2GWbOb8/lElSiW3mDDPv1/PM88iZM+e8OZfgfc/5nM+RCIIggIiIiMhASMUOQERERNSSWG6IiIjIoLDcEBERkUFhuSEiIiKDwnJDREREBoXlhoiIiAwKyw0REREZFBOxA+iaWq1GTk4ObGxsIJFIxI5DREREDSAIAkpKSuDm5gaptP5zM0ZXbnJycqBUKsWOQURERE2QlZUFDw+PetcxunJjY2MD4M7BsbW1FTkNERERNURxcTGUSqXm73h9jK7c1F6KsrW1ZbkhIiJqZRoypIQDiomIiMigsNwQERGRQWG5ISIiIoPCckNEREQGheWGiIiIDArLDRERERkUlhsiIiIyKCw3REREZFBYboiIiMigsNwQERGRQWG5ISIiIoPCckNEREQGheWmBZ3PK0bWzXKxYxARERk1lpsWsvdsPsZ9fQSvrE9EVY1a7DhERERGi+Wmhfi72cLcVIZTV4vw6Z7zYschIiIyWiw3LcTdzgKfT+wGAPj+cDr+OJMnciIiIiLjxHLTgob5O2PWgPYAgDc2ncLVWxx/Q0REpGssNy1s4chO6Ka0Q3FFDV79JQnVKo6/ISIi0iWWmxZmZiLF11OCYGtugqTMQiyOShU7EhERkVFhudECpYMlFt8df/PtwcvYfy5f5ERERETGg+VGS0Z0ccGMfl4AgAWbTiGn8La4gYiIiIwEy40WhY/uhK7uChSWV3P8DRERkY6w3GiR3ESG5c/0gI3cBAlXbuH97WcgCILYsYiIiAway42WebaxxJKnu0EiAX4+kYmVBy+LHYmIiMigsdzowPAuLnhnjD8AYNHu89h+KkfkRERERIaL5UZHnhvQHjP7ewEA3th4CrHpN8UNREREZKBYbnTo7TH+GNHFGVUqNV74MR6XrpWKHYmIiMjgsNzokEwqwZeTgtBdaYei29WY8UMsrpVUih2LiIjIoLDc6JiFmQzfTw9GuzaWyLp5G8+vjUN5VY3YsYiIiAwGy40I2ljL8cOMXrCzNMWpq0V4jXPgEBERtRiWG5F4t7XGd2HBMDORYt+5AsyPPIkaFhwiIqJmY7kRUbCXA1Y+2xNmMil2puRiwaZTUKk5yR8REVFzsNyI7NFOTlg+tQdMpBL8djIH/29zMtQsOERERE3GcqMHhvk746spQZBJJdiSeBVvbU1hwSEiImoilhs9MaqrK76c1B1SCRAZl4V3t5/mc6iIiIiaQG/KzaJFiyCRSDB//vyHrrNq1SoMHDgQ9vb2sLe3R2hoKGJjY3UXUsvGdnPTPIdq3fFM/GfHWRYcIiKiRtKLchMXF4eVK1ciMDCw3vWio6MxZcoUHDhwAMeOHYNSqcTw4cORnZ2to6Ta90SQBz6bcOc4/HAkA+9vP8NLVERERI0gerkpLS3F1KlTsWrVKtjb29e77s8//4yXX34Z3bt3R6dOnfDdd99BrVZj//79D/1MZWUliouL67z03cRgJSKe7AqJBFh77AoWbDrFeXCIiIgaSPRyM3fuXIwZMwahoaGN/mx5eTmqq6vh4ODw0HUiIiKgUCg0L6VS2Zy4OjOltye+nNQdJlIJtiZlY866BFRUq8SORUREpPdELTeRkZFITExEREREkz6/cOFCuLm51VuMwsPDUVRUpHllZWU1Na7Ojevujm/DekJ+d6K/6atjUVJRLXYsIiIivSZaucnKysK8efPw888/w9zcvNGfX7RoESIjI7F169Z6Py+Xy2Fra1vn1ZoM6eSMH5/rDRu5CU6k38SUVcdxo5QP2yQiInoYiSDS7Tjbtm3DE088AZlMplmmUqkgkUgglUpRWVlZ5717ff755/joo4+wb98+BAcHN2q/xcXFUCgUKCoqalVF53R2EaavjsWNsip4t7XCull94GZnIXYsIiIinWjM32/RztwMHToUKSkpOHnypOYVHByMqVOn4uTJkw8tNp999hk+/PBD7Nmzp9HFpjULcFdg0+wQuCnMcflaGZ5acRTn8/R/cDQREZGuiVZubGxsEBAQUOdlZWWFNm3aICAgAAAQFhaG8PBwzWc+/fRTvPPOO1i9ejW8vLyQl5eHvLw8lJaWivVt6JR3W2tsntMPHdpaIaeoAhNXHMPBtGtixyIiItIrot8tVZ/MzEzk5uZqvl6xYgWqqqrw1FNPwdXVVfP6/PPPRUypW252Ftgypx/6tHdASWUNZq6JQ2RsptixiIiI9IZoY27E0lrH3PxdZY0K4VtS8GvSnQkM5zzSAW8O94NUKhE5GRERUctrFWNuqHnkJjIsebob5g31BQCsiL6EVyOTOBcOEREZPZabVkwikeD1YR2xZGI3mMok2Jmci2d4qzgRERk5lhsDMKGnB358rg9szU2QmFmIx78+gjM5RWLHIiIiEgXLjYEI6dAGv77cH15tLJFdeBtPrTiGncm5//xBIiIiA8NyY0B8nKzx29wBGOjriNvVKsxdn4jFUef5VHEiIjIqLDcGRmFpijUze+OlQd4AgOUHLuGFH+NRzGdSERGRkWC5MUAyqQThozvjy0ndITeRYv/5Ajyx/AguXzOOyQ6JiMi4sdwYsPFB7tg0OwSuCnNculaGccuPYO/ZfLFjERERaRXLjYEL9LDD9lcGILidPUoqavDCj/H4bM951KjUYkcjIiLSCpYbI9DWRo5fXuyL5/q3BwD8L/oSwlbH4jrnwyEiIgPEcmMkTGVSvDvWH18/EwRLMxmOXrqBMcsOIeHKTbGjERERtSiWGyPzWKAbtr/SHz5O1sgvrsSklcfxw5F0GNkjxoiIyICx3BghHycb/Da3Px4LdEWNWsAHv5/FK+uTeLs4EREZBJYbI2UlN8FXU4Lw/lh/mEgl2JmSi8eWHUby1UKxoxERETULy40Rk0gkmNG/PTbP6QcPewtk3izHhBVHsfowL1MREVHrxXJD6K60w87XBmJkFxdUqwT8Z8dZvPRTAorKeZmKiIhaH5YbAgAoLEyx4tke+ODxLjCTSfHH2XyMXnYIiZm3xI5GRETUKCw3pCGRSDC9nxd+fbkf2t19uvjT3xzD8gMXoeLDN4mIqJVguaH7BLgrsOPVAZq7qRZHpeLZ704gr6hC7GhERET/iOWGHsjG3BRfTQnCZ08FwtJMhmOXb2Dk0oOIOpMndjQiIqJ6sdzQQ0kkEjwdrMSOVwegq7sCheXVeOmnBPzf1hTcrlKJHY+IiOiBWG7oH3m3tcaWOf3w0iBvAMDPJzIx9uvDOJtTLHIyIiKi+7HcUIOYmUgRProz1s3qAycbOS4WlGL88iP49uAlqDnYmIiI9AjLDTXKAF9H7J43EKGdnVGlUuOTXefxzHfHkV14W+xoREREAFhuqAnaWMuxKqwnFj3ZFZZmMhy/fBMjvzyIbUnZnNmYiIhEx3JDTSKRSDC5tyd2vTYQQZ52KKmowfwNJ/HKL0koLK8SOx4RERkxlhtqFi9HK2x6KQT/GtYRMqkEO5NzMfLLQziYdk3saEREZKRYbqjZTGRSvDbUF7/O6QdvRyvkFVcgbHUs/m9rCsoqa8SOR0RERoblhlpMN6Uddrw2ADP6eQG4c8v4yKUHceLyDXGDERGRUWG5oRZlaWaC9x/vgvXP94G7nQWybt7G5FXH8eGOs6io5sR/RESkfSw3pBX9fByxZ/5ATO6lhCAA3x9Ox+hlh3Ayq1DsaEREZOBYbkhrbMxNsWhCIH6Y0QtONnJcvlaGJ/93BBG7zvEsDhERaQ3LDWndo52c8MfrgzC+uxvUArDy4GWMXnYICVduih2NiIgMEMsN6YSdpRm+nByEVWHBmrM4T31zDB/8fgblVbyjioiIWg7LDenUMH9n7P3XYEzs6QFBAH44koGRXx7CsUu8o4qIiFoGyw3pnMLCFIsndsOamb3gqjBH5s1yTFl1HG9tTUFxRbXY8YiIqJVjuSHRPOJ3ZyzOlN6eAID1JzIRuiQGe07niZyMiIhaM5YbEpWNuSkinuyKX17oi/aOVigoqcTsdQl46ad45BdXiB2PiIhaIZYb0gshHdpg97yBmPtoB5hIJYg6k4/QJTH4+cQVqNV80jgRETUcyw3pDXNTGd4c0Qm/vzoA3TwUKKmswf9tPY1J3x5DWn6J2PGIiKiVYLkhvdPZ1Ra/vtwf7zzmD0szGeIybmH00kP4dM953K7i5H9ERFQ/vSk3ixYtgkQiwfz58+tdb9OmTejUqRPMzc3RtWtX7Nq1SzcBSadkUglmDWiPvf8ajGH+zqhRC1gRfQnD/huDP8/nix2PiIj0mF6Um7i4OKxcuRKBgYH1rnf06FFMmTIFs2bNQlJSEsaPH4/x48fj9OnTOkpKuuZuZ4FVYcH4dlpPuCnMcfXWbTy3Jh6zf0pAbtFtseMREZEeEr3clJaWYurUqVi1ahXs7e3rXXfp0qUYOXIk3nzzTXTu3BkffvghevToga+//lpHaUksw7u4YO+/BuOlQd6QSSXYcyYPoUtisOrgZVSr1GLHIyIiPSJ6uZk7dy7GjBmD0NDQf1z32LFj9603YsQIHDt27KGfqaysRHFxcZ0XtU5WchOEj+6Mna8NQM929iirUuHjXecwaukhHL5wXex4RESkJ0QtN5GRkUhMTERERESD1s/Ly4Ozs3OdZc7OzsjLe/ikbxEREVAoFJqXUqlsVmYSXycXW2x6KQSfTQhEGyszXCwoxbPfn8DLPycgu5CXqoiIjJ1o5SYrKwvz5s3Dzz//DHNzc63tJzw8HEVFRZpXVlaW1vZFuiOVSvB0LyX+fOMRzOjnBakE2JWSh6FLovH1nxdQUc27qoiIjJVo5SYhIQEFBQXo0aMHTExMYGJigpiYGCxbtgwmJiZQqe7/4+Ti4oL8/Lp3yuTn58PFxeWh+5HL5bC1ta3zIsOhsDDF+493wc7XBqK3lwMqqtX4/I80jPjyIKLO5EEQOAEgEZGxEa3cDB06FCkpKTh58qTmFRwcjKlTp+LkyZOQyWT3fSYkJAT79++vs2zv3r0ICQnRVWzSU51dbbHhpb5YOrk7nGzkuHKjHC/9lIBnVp3A2RyOsyIiMiYmYu3YxsYGAQEBdZZZWVmhTZs2muVhYWFwd3fXjMmZN28eBg8ejCVLlmDMmDGIjIxEfHw8vv32W53nJ/0jkUgwrrs7hnZ2xjfRl/Dtocs4dvkGxnx1CJN7KbFguB8creVixyQiIi0T/W6p+mRmZiI3N1fzdb9+/bB+/Xp8++236NatGzZv3oxt27bdV5LIuFnLTfDGCD/s/9dgPBboCkEAfonNwiOLo/FNzCVU1nA8DhGRIZMIRjYoobi4GAqFAkVFRRx/YyTiMm7iwx1nkXy1CADgYW+BN0f4YWygG6RSicjpiIioIRrz95vlhoyCWi1ga1I2Pos6j/ziSgBAgLstwkd1Rn8fR5HTERHRP2G5qQfLjXG7XaXC6iPpWBF9CaWVNQCAwR3b4t+jOqGzK38eiIj0FctNPVhuCABulFbiqz8vYt3xK6hRC5BIgCeDPPD6MF942FuKHY+IiP6G5aYeLDd0r4zrZVj8Ryp2Jt8ZuG4qk2Bqn3Z4+dEOcLLR3uSSRETUOCw39WC5oQdJyryFz/9IxZGLNwAAFqYyzOjvhdmDOkBhaSpyOiIiYrmpB8sN1efIxetYHJWKk1mFAAAbcxO8NMgbM/u3h5VctGmhiIiMHstNPVhu6J8IgoB95wrweVQqUvNLAAAOVmZ4YaA3wkLaseQQEYmA5aYeLDfUUGq1gN+Tc/DfvWnIuFEOALC3NMULg7wRFuIFa5YcIiKdYbmpB8sNNVaNSo3tp3Lw1Z8XkX69DABLDhGRrrHc1IPlhprqQSXHztIUz/Vvj+khXhx4TESkRSw39WC5oeaqUanxe3IOlu3/q+RYmcnwbN92mDWgPZxseQs5EVFLY7mpB8sNtZQalRq7Tufhfwcu4nzenYHHZiZSPB3sgZcGdYDSgZMBEhG1FJaberDcUEsTBAF/ni/A8gMXkZhZCACQSSV4LNAVLw7yRhc3hbgBiYgMAMtNPVhuSFsEQcCJ9JtYfuAiDl24rlk+wMcRLw7yxkBfR0gkfAo5EVFTsNzUg+WGdCHlahG+PXQZO5NzoL77X1hnV1u8OKg9Hgt0g6lMKm5AIqJWhuWmHiw3pEtZN8vx/eF0bIzPQnmVCgDgqjDH9H5emNxLCTtLM5ETEhG1Diw39WC5ITEUllfh5xOZ+OFIBq6XVgK48/yqCT3dMaNfe/g4WYuckIhIv7Hc1IPlhsRUUa3C9lM5+OFIBs7lFmuWD+7YFs8NaI9BHJdDRPRALDf1YLkhfSAIAo5fvonVR9Kx71w+av8r7NDWCmEhXniyhztszDkpIBFRLZaberDckL65cqMMa49ewcb4LJRW1gC4MynghJ4eCAtpBx8nG5ETEhGJj+WmHiw3pK9KKqqxNSkba49m4NK1Ms3yfh3aICzEC6GdnWDCu6yIyEix3NSD5Yb0nSAIOHrpBtYezcC+c/maW8ldbM0xubcSk3t5wkXBRzwQkXFhuakHyw21JtmFt/Hz8SuIjMvCzbIqAHdmPw7t7ISpfdphgI8jpFIOQCYiw8dyUw+WG2qNKmtU2HM6Dz8fz0Rsxk3N8nZtLPFMb09M6OkBR2u5iAmJiLSL5aYeLDfU2qXll+Dn41fwa2I2Su4OQDaVSTC8iwue6e2JEO82PJtDRAaH5aYeLDdkKMqrarD9ZA5+ic3EqatFmuWeDpaY3FuJp3p6wMmGY3OIyDCw3NSD5YYM0ZmcIkTGZmFb0l9nc0ykEoR2dsak3koM8m0LGc/mEFErxnJTD5YbMmTlVTXYkZyLX2IzkZRZqFnuqjDHxGAlng72gIe9pXgBiYiaiOWmHiw3ZCzO5xVjQ1wWtiZlo7C8GgAgkQADfdtiUrASof5OkJvIRE5JRNQwLDf1YLkhY1NRrcIfZ/OxIS4TRy7e0Cx3sDLD+O7umNRLCT8XzoJMRPqN5aYeLDdkzDJvlGNDfCY2J1xFfnGlZnk3pR0mBSsxtpsrn2lFRHqJ5aYeLDdEQI1KjYMXrmFDXBb2nytAzd1pkC1MZRjd1RWTeinRy8ueTygnIr3BclMPlhuiuq6VVGJbUjY2xGfhYkGpZnl7RytMDPbAUz084GTLW8qJSFwsN/VguSF6MEEQkJhZiI1xWdiRnIOyKhWAO497eNSvLSYGKzGkkxNM+fBOIhIBy009WG6I/llZZQ12puRiY1wW4q/c0ix3tJZjQg93TAxWwsfJWsSERGRsWG7qwXJD1DgXC0qxKT4LWxKzcb30r0HIwe3s8XQvJcZ0dYWV3ETEhERkDFhu6sFyQ9Q01So1DpwvwMb4LBxIvQbV3UHIVmYyjO3mhqd7KRGktOMgZCLSCpaberDcEDVffnEFtiRexab4q0i/XqZZ3tHZGpN6eeKJIHc4WJmJmJCIDA3LTT1YbohajiAIiE2/iQ3xWdiVkouKajUAwEwmxbAuzpgUrMQAH0c+pZyImo3lph4sN0TaUVxRje0nc7AhLgsp2X89pdzdzgKTeikxMdgDrgoLERMSUWvGclMPlhsi7TuTU4SNd59rVVxx5ynlUgnwiJ8TJvdS4lHeUk5EjcRyUw+WGyLdqahWYffpXETGZuFE+k3N8rY2ckzs6YHJvTzh2YZPKSeif9aYv9+i/l+nFStWIDAwELa2trC1tUVISAh2795d72e+/PJL+Pn5wcLCAkqlEq+//joqKip0lJiIGsPcVIYngjyw4aUQ/LlgMF4a7A1HazNcK6nE/6IvYdDiA3j2uxPYkZyDqhq12HGJyECIeubm999/h0wmg6+vLwRBwNq1a7F48WIkJSWhS5cu962/fv16PPfcc1i9ejX69euHtLQ0zJgxA5MnT8YXX3zRoH3yzA2RuKpq1Nh/Lh+/xGXh0IVrqP0N1MbKDBN6emByLyW823KCQCKqq1VflnJwcMDixYsxa9as+9575ZVXcO7cOezfv1+zbMGCBThx4gQOHz7coO2z3BDpj6yb5dgYn4WN8Vl1nlLe19sBU3p7YmSAC+QmMhETEpG+aMzfb72ZVlSlUmHTpk0oKytDSEjIA9fp168f1q1bh9jYWPTu3RuXL1/Grl27MG3atIdut7KyEpWVf/3SLC4ubvHsRNQ0SgdLLBjuh3lDfXEg9RoiYzNxILUAxy/fxPHLN+FgZYaneDaHiBpJ9DM3KSkpCAkJQUVFBaytrbF+/XqMHj36oesvW7YMb7zxBgRBQE1NDWbPno0VK1Y8dP33338fH3zwwX3LeeaGSD/lFN7GhrgsbIjLQl7xX+PpQrzbYEofT4zo4syzOURGqFVdlqqqqkJmZiaKioqwefNmfPfdd4iJiYG/v/9960ZHR2Py5Mn46KOP0KdPH1y8eBHz5s3DCy+8gHfeeeeB23/QmRulUslyQ6TnalRqRKdewy93z+bcfdoDHKzMMLGnB6b09oSXo5W4IYlIZ1q83Dg4ODQqgEQiQWJiItq1a9eozwFAaGgoOnTogJUrV9733sCBA9G3b18sXrxYs2zdunV48cUXUVpaCqn0n2/+4pgbotYn++7ZnI1/O5szwMcRz/TxxDB/Z86bQ2TgWnzMTWFhIb788ksoFIp/XFcQBLz88stQqVQNS/s3arW6zpmWe5WXl99XYGQymWa/RGSY3O0s8K9hHfHaEB/8eb4A62MzEZN2DYcvXsfhi9fR1kaOp4PvzJujdOC8OUTGrsEDiidPngwnJ6cGrfvqq682aL3w8HCMGjUKnp6eKCkpwfr16xEdHY2oqCgAQFhYGNzd3REREQEAGDt2LL744gsEBQVpLku98847GDt2rKbkEJHhMpFJMbyLC4Z3cUHWzXJExmViQ9xVXCupxPIDl/C/6EsY3LEtpvZph0f92sKEZ3OIjFKDyo1a3bjJtUpKShq0XkFBAcLCwpCbmwuFQoHAwEBERUVh2LBhAIDMzMw6Z2refvttSCQSvP3228jOzkbbtm0xduxYfPzxx43KR0Stn9LBEm+O6IT5oR2x92w+1p/IxOGL1xGdeg3RqdfgYmuOSb2UmNxbyWdaERmZBg8o3rFjB0aPHt2gcS36jGNuiAxXxvUy/BKbiU0JV3GzrArAnWdaDenkjKl9PDGoY1vI+IRyolZJK3dLmZiYwNnZGTNmzMDMmTPh4+PTImF1jeWGyPBV1qgQdSYfPx+/UueZVu52FpjSW4mng5VwsjUXMSERNZZWyk1WVhZ++OEHrF27FhkZGRgwYACef/55PPXUU7CwaD2nfFluiIzLxYJS/BKbic0JV1F0uxoAYCKVILSzM57p44kBPo6Q8mwOkd7T+jw3Bw4cwJo1a7BlyxaYmJhg8uTJmDVrFnr16tXk0LrCckNknCqqVdiVkov1JzIRf+WWZrnSwQKTe3liYrAHnGx4NodIX+lsEr+SkhJERkZizZo1OH78OAICAnDq1Kmmbk4nWG6IKDWvBOtPXMGvSdkoqagB8NfZnCl9PDGQZ3OI9I5OZyi+fPkyVq9ejRUrVqC4uBjV1dXN2ZzWsdwQUa3bVSrsTMnFL7GZSLjnbI6HvQWeDlZiYrAH77Qi0hNaLze3b9/Gpk2bsHr1ahw6dAjt27fHzJkzMWPGDLi7uzc5uC6w3BDRg6TmleCX2Ez8mngVxXfP5kglwKN+TpjUS4khnZw4bw6RiLRWbo4fP47Vq1dj48aNqKqqwpNPPolZs2bh0UcfbXZoXWG5IaL61I7NiYzLQuw9d1o52cjxVE8PTOqlRLs2fKYVka5ppdz4+/sjNTUVQUFBmDVrFp555pkGPY5B37DcEFFDXbpWig1xWdiScBU37s6bAwB92jvg6WAlRnV1gaVZgyd6J6Jm0Eq5ee211zBr1ix069atRUKKheWGiBqrqkaNfefyERmXhUMXrqH2t6a13ARju7liYrASQUo7SCQchEykLTodUNzasNwQUXPkFN7GloSr2JRwFZk3yzXLfZysMaGHB54IcoeLgreUE7W0Fi83PXr0wP79+2Fvb9+gAAMGDMCGDRv0cnAxyw0RtQS1WkBsxk1sjM/CrpRcVFTfeQafVAL093HEUz09MNzfBRZmfKgvUUto8XIjlUrx559/wsHBoUEB+vXrh+TkZHh7ezcssQ6x3BBRSyupqMbO5FxsSbyKuIy/bim3lptgTFdXPNnDHb28HDh3DlEzaKXcSCQSNPQKlkQiwYULF1huiMjoXLlRhi2J2fg18Squ3rqtWe5uZ4HHu7thfHd3+LnYiJiQqHVq8XJz5cqVRofw8PCATKZ/p2NZbohIF9RqAXEZN7El8Sp2p+ShpLJG814nFxs8EeSOx7u7cZJAogbigOJ6sNwQka5VVKvw5/kCbE3KRnRqAapVd37tSiRALy8HjO3mhlEBLnC0louclEh/sdzUg+WGiMRUWF6FnSm5+C0pB7EZf00SKJNK0K9DG4wNdMOILi5QWJqKmJJI/7Dc1IPlhoj0RXbhbexKzsXvyTlIvlqkWW4qk2CQb1uM6uqKYf7OUFiw6BCx3NSD5YaI9FHG9TLsSM7BjuRcnM8r0Sw3lUkwwMcRo7q6Yri/M+wszURMSSQelpt6sNwQkb5Lyy/BrpRc7ErJRVp+qWa5iVSCfj6OGBXgguH+zmjDMTpkRLRebgoLC7F582ZcunQJb775JhwcHJCYmAhnZ2e9nLjvXiw3RNSaXCwowa6UPOxKqXtGRyoBerd3wMguLhgZ4MpZkcngabXcJCcnIzQ0FAqFAhkZGUhNTYW3tzfefvttZGZm4scff2xWeG1juSGi1urytVLsPp2HPafzkJJdVOe9IE87jApwwcgurvBsYylSQiLt0Wq5CQ0NRY8ePfDZZ5/BxsYGp06dgre3N44ePYpnnnkGGRkZzcmudSw3RGQIsm6WI+rMnaKTkHkL9/4m93e1xcgAF4wKcIGvMycMJMOg1XKjUCiQmJiIDh061Ck3V65cgZ+fHyoqKpoVXttYbojI0BQUV9wpOmfycPzyTajUf/1a79DW6m7RcUUXN1s+uZxarcb8/TZp7MblcjmKi4vvW56Wloa2bds2dnNERNRMTrbmmBbihWkhXrhZVoV9Z/Ox50weDl+4jkvXyrD8wCUsP3AJXm0sMSbQFWO6uqGzqw2LDhmsRp+5ef7553Hjxg1s3LgRDg4OSE5Ohkwmw/jx4zFo0CB8+eWXWoraMnjmhoiMRXFFNQ6cL8DulDwcSC1AZY1a8563oxXGBLrisUA3PuuKWgWtXpYqKirCU089hfj4eJSUlMDNzQ15eXkICQnBrl27YGVl1azw2sZyQ0TGqLSyBvvP5WNnci6i066h6p6i4+9qiyd73HnWlZMN77oi/aSTeW4OHz6M5ORklJaWokePHggNDW1SWF1juSEiY1dSUY0/zxfg91O5iEn761lXMqkEA30d8WQPDwz3d4a5qf49/JiMFyfxqwfLDRHRX26VVWFHSi5+TbyKpMxCzXIbuQke7+6GsBAvXrYivaDVcrNs2bIHb0gigbm5OXx8fDBo0CDIZPrZ+FluiIge7PK1UmxLysavSdm4euu2ZnlfbwdMD/HCMH9nmMikIiYkY6bVctO+fXtcu3YN5eXlsLe3BwDcunULlpaWsLa2RkFBAby9vXHgwAEolcqmfxdawnJDRFQ/tVrA8fQbWHf8CqLO5GtuLXdVmGNqH09M7u0JRz76gXSsMX+/G13BP/nkE/Tq1QsXLlzAjRs3cOPGDaSlpaFPnz5YunQpMjMz4eLigtdff73J3wAREYlHKpWgXwdH/G9qTxxe+CheHeIDR2sz5BZV4PM/0tAv4k+899tpFBTr97xmZLwafeamQ4cO2LJlC7p3715neVJSEiZMmIDLly/j6NGjmDBhAnJzc1sya4vgmRsiosarrFFhV0ou1hy9glNZhQAAuYkU0/q2w+xHOvBMDmmdVs/c5Obmoqam5r7lNTU1yMvLAwC4ubmhpKTkvnWIiKh1kpvI8ESQB36b2x/rn++Dnu3sUVmjxneH0zHoswP4dM953CqrEjsmEYAmlJtHH30UL730EpKSkjTLkpKSMGfOHAwZMgQAkJKSgvbt27dcSiIi0hv9fByxeXYI1szshUAPBcqrVFgRfQkDPzuAr/ZfqDOHDpEYGl1uvv/+ezg4OKBnz56Qy+WQy+UIDg6Gg4MDvv/+ewCAtbU1lixZ0uJhiYhIP0gkEjzi54Tf5vbHqrBgdHa1RWllDZbsTcNjXx1CYuYtsSOSEWvyPDfnz59HWloaAMDPzw9+fn4tGkxbOOaGiKjlqdUCtp/KwYc7zuJGWRUkEmB6iBfeHOEHK3mjH2NIdB9O4lcPlhsiIu25VVaFD3eexa+J2QAAdzsLfPJkVwzuyAcrU/NovdxcvXoV27dvR2ZmJqqq6g4g++KLLxq7OZ1iuSEi0r6YtGt469cUZBfemQzwySB3vDe2CxSWpiIno9aqMX+/G32ucP/+/Xj88cfh7e2N8+fPIyAgABkZGRAEAT169GhyaCIiMhyDO7bFH68PwpI/0vDD0XT8mpSNk1mF+G56MLzbWosdjwxcowcUh4eH44033kBKSgrMzc2xZcsWZGVlYfDgwZg4caI2MhIRUStkJTfBu2P9sWVOP7gpzHH5ehnGLz+CQxeuiR2NDFyjy825c+cQFhYGADAxMcHt27dhbW2N//znP/j0009bPCAREbVuPTzt8dsrA9CznT2KK2ow44c4rDmSDiMb8kk61OhyY2VlpRln4+rqikuXLmneu379esslIyIig9HWRo71L/TBhB4eUKkFvP/7Wby19TTnxCGtaHS56du3Lw4fPgwAGD16NBYsWICPP/4Yzz33HPr27duoba1YsQKBgYGwtbWFra0tQkJCsHv37no/U1hYiLlz58LV1RVyuRwdO3bErl27GvttEBGRjslNZPh8YiD+b3RnSCTAL7GZmPb9CdzkzMbUwhp9t9Tly5dRWlqKwMBAlJWVYcGCBTh69Ch8fX3xxRdfoF27dg3e1u+//w6ZTAZfX18IgoC1a9di8eLFSEpKQpcuXe5bv6qqCv3794eTkxPeeustuLu748qVK7Czs0O3bt0atE/eLUVEJL4D5wvw6i9JKK2sgVcbS2x8KQROtuZixyI91qrnuXFwcMDixYsxa9as+9775ptvsHjxYpw/fx6mpg27nbCyshKVlZWar4uLi6FUKlluiIhEdiG/BDPXxOHqrdvwc7bBxpdCeKs4PZRWH5zp7e2NGzdu3Le8sLAQ3t7ejd2chkqlQmRkJMrKyhASEvLAdbZv346QkBDMnTsXzs7OCAgIwCeffAKVSvXQ7UZEREChUGheSqWyyRmJiKjl+Drb4JcX+sLJRo7U/BLMXBOL8qr7H8xM1FiNLjcZGRkPLBOVlZXIzs5udICUlBRYW1tDLpdj9uzZ2Lp1K/z9/R+47uXLl7F582aoVCrs2rUL77zzDpYsWYKPPvroodsPDw9HUVGR5pWVldXojEREpB1KB0v8NKsPFBamSMwsxOx1iRxkTM3W4MtS27dvBwCMHz8ea9euhUKh0LynUqmwf/9+7N27F6mpqY0KUFVVhczMTBQVFWHz5s347rvvEBMT88CC07FjR1RUVCA9PR0ymQzAnRmRFy9ejNzc3Abtj2NuiIj0T8KVW3j2uxO4Xa3CY4GuWDo5CDKpROxYpEe0MuZGKr1zkkcikdw3N4GpqSm8vLywZMkSPPbYY02MfUdoaCg6dOiAlStX3vfe4MGDYWpqin379mmW7d69G6NHj0ZlZSXMzMz+cfssN0RE+ulg2jXMWhuHapWAqX088dH4AEgkLDh0h1bG3KjVaqjVanh6eqKgoEDztVqtRmVlJVJTU5tdbGr3c+8A4Hv1798fFy9ehFr91ynLtLQ0uLq6NqjYEBGR/hrUsS3+O6k7JBLg5xOZWPJHmtiRqJVq9Jib9PR0ODo6tsjOw8PDcfDgQWRkZCAlJQXh4eGIjo7G1KlTAQBhYWEIDw/XrD9nzhzcvHkT8+bNQ1paGnbu3IlPPvkEc+fObZE8REQkrscC3fDx+K4AgK8PXMS641dETkStUYMenLls2bIGb/C1115r8LoFBQUICwtDbm4uFAoFAgMDERUVhWHDhgEAMjMzNZfDAECpVCIqKgqvv/46AgMD4e7ujnnz5mHhwoUN3icREem3Z/p44mZZJT7/Iw3/2XEWvds7oKOzjdixqBVp0Jib9u3bN2xjEgkuX77c7FDaxDE3RET6TxAEzFwTh+jUa+jkYoPfXukPuYlM7FgkolY9iZ+2sdwQEbUOBSUVGPnlIdwsq8LzA9rj7ccePE0IGQetTuJ3L0EQ+FRXIiLSCicbc3w2IRAA8N3hdBy+wIczU8M0qdz8+OOP6Nq1KywsLGBhYYHAwED89NNPLZ2NiIiMXKi/M6b28QQALNh0Erf4kE1qgEaXmy+++AJz5szB6NGjsXHjRmzcuBEjR47E7Nmz8d///lcbGYmIyIi9PcYf3m2tkF9ciX//mswrBvSPGj3mpn379vjggw8QFhZWZ/natWvx/vvvIz09vUUDtjSOuSEian1OZxfhif8dQbVKwKcTumJSL0+xI5GOaXXMTW5uLvr163ff8n79+jX4EQhERESNEeCuwL+G+QEAPvj9LNKvl4mciPRZo8uNj48PNm7ceN/yDRs2wNfXt0VCERER/d2Lg7zR19sB5VUqzN9wEjUqPmCTHqxBk/jd64MPPsCkSZNw8OBB9O/fHwBw5MgR7N+//4Glh4iIqCXIpBJ88XR3jPzyIE5lFWJzwlVM7s3LU3S/Bp+5OX36NABgwoQJOHHiBBwdHbFt2zZs27YNjo6OiI2NxRNPPKG1oERERG52Fnht6J2rBP/dl4bbVSqRE5E+atRTwXv16oXnn38ekydPho1N65wKmwOKiYhat8oaFYYuicHVW7fx5gg/zH3UR+xIpANaGVAcExODLl26YMGCBXB1dcWMGTNw6NChZoclIiJqDLmJDG8MvzO4+JvoS7jJuW/obxpcbgYOHIjVq1cjNzcXX331FdLT0zF48GB07NgRn376KfLy8rSZk4iISOPxbm7o4maLksoafPXnBbHjkJ5p9N1SVlZWmDlzJmJiYpCWloaJEydi+fLl8PT0xOOPP66NjERERHVIpRL8e1QnAMC641eQeaNc5ESkT5r1bCkfHx+89dZbePvtt2FjY4OdO3e2VC4iIqJ6DfRti4G+jqhWCfj8j1Sx45AeaXK5OXjwIGbMmAEXFxe8+eabePLJJ3HkyJGWzEZERFSvhSPvnL3ZfioHp7OLRE5D+qJR5SYnJweffPIJOnbsiEceeQQXL17EsmXLkJOTg1WrVqFv377ayklERHSfAHcFxnd3AwAs2n1e5DSkLxo8id+oUaOwb98+ODo6IiwsDM899xz8/Py0mY2IiOgfLRjuh10peTh88ToOpl3DoI5txY5EImtwuTE1NcXmzZvx2GOPQSaTaTMTERFRgykdLDEtpB2+P5yORbvPY4CPI6RSidixSEQNviy1fft2jBs3jsWGiIj0ziuP+sDG3ARnc4vx26lsseOQyJp1txQREZE+sLcyw5xHOgAAlh+4hAZOvk8GiuWGiIgMwrN928HSTIaLBaU4dvmG2HFIRCw3RERkEGzNTfFEkDsA4KdjV0ROQ2JiuSEiIoMRFuIFAPjjbD5yi26LG4ZEw3JDREQGw8/FBr3bO0ClFvDLiUyx45BIWG6IiMighIW0AwCsj81CVY1a5DQkBpYbIiIyKCO6uMDJRo7rpZXYcyZP7DgkApYbIiIyKKYyKZ7p4wkA+OlYhrhhSBQsN0REZHCe6e0JE6kEcRm3cDanWOw4pGMsN0REZHCcbM0xIsAFAPDT8Qxxw5DOsdwQEZFBCut7Z2DxtqQcFN2uFjkN6RLLDRERGaTe7R3g52yD29UqbE64KnYc0iGWGyIiMkgSiQTT7t4Wvu74FajVfN6UsWC5ISIig/VEkDts5CZIv16Gwxevix2HdITlhoiIDJaV3AQTenoAAH7k86aMBssNEREZtGfvDiz+83w+sgv5vCljwHJDREQGzcfJGn29HaAWgJ3JOWLHIR1guSEiIoM3pqsrAGD3aT6OwRiw3BARkcEb0cUFEgmQlFmI3CJemjJ0LDdERGTwnGzN0dPTHgCwh2dvDB7LDRERGYWRdx/HwEtTho/lhoiIjMKou+Nu4jJu4lpJpchpSJtELTcrVqxAYGAgbG1tYWtri5CQEOzevbtBn42MjIREIsH48eO1G5KIiAyCu50FunkoIAjAH2d59saQiVpuPDw8sGjRIiQkJCA+Ph5DhgzBuHHjcObMmXo/l5GRgTfeeAMDBw7UUVIiIjIEIwPu3jWVwnJjyEQtN2PHjsXo0aPh6+uLjh074uOPP4a1tTWOHz/+0M+oVCpMnToVH3zwAby9vXWYloiIWrtRd8fdHLt8A7fKqkROQ9qiN2NuVCoVIiMjUVZWhpCQkIeu95///AdOTk6YNWtWg7ZbWVmJ4uLiOi8iIjJOXo5W6ORiA5VawN5z+WLHIS0RvdykpKTA2toacrkcs2fPxtatW+Hv7//AdQ8fPozvv/8eq1atavD2IyIioFAoNC+lUtlS0YmIqBUafXdgMW8JN1yilxs/Pz+cPHkSJ06cwJw5czB9+nScPXv2vvVKSkowbdo0rFq1Co6Ojg3efnh4OIqKijSvrKysloxPREStTO2lqUMXrqG4olrkNKQNEkEQBLFD3Cs0NBQdOnTAypUr6yw/efIkgoKCIJPJNMvUajUAQCqVIjU1FR06dPjH7RcXF0OhUKCoqAi2trYtG56IiFqFoUuicelaGb6c1B3jg9zFjkMN0Ji/36Kfufk7tVqNysr75x/o1KkTUlJScPLkSc3r8ccfx6OPPoqTJ0/ychMRETXYqNq7pk7nipyEtMFEzJ2Hh4dj1KhR8PT0RElJCdavX4/o6GhERUUBAMLCwuDu7o6IiAiYm5sjICCgzuft7OwA4L7lRERE9RkZ4IKvD1xETNo1lFfVwNJM1D+H1MJE/V+zoKAAYWFhyM3NhUKhQGBgIKKiojBs2DAAQGZmJqRSvTu5RERErVwXN1soHSyQdfM2olOvaQYZk2HQuzE32sYxN0REBAARu85h5cHLeCzQFV8/00PsOPQPWvWYGyIiIl2ofZDmgfMFqKhWiZyGWhLLDRERGaVuHnZwVZijrEqFQxeuix2HWhDLDRERGSWpVIIRXe6cvdmdwrumDAnLDRERGa3achOTdg1GNgTVoLHcEBGR0erRzg7mplLcKKtCWn6p2HGohbDcEBGR0ZKbyBDczgEAcOwSx90YCpYbIiIyaiEd2gAAjl2+IXISaiksN0REZNRqy82J9JtQqznuxhCw3BARkVHr6q6AlZkMheXVOJdXLHYcagEsN0REZNRMZVL0al877oaXpgwByw0RERm9EO+7425YbgwCyw0RERm9fh0cAQCx6TdRo1KLnIaai+WGiIiMnr+bLWzNTVBSWYMzORx309qx3BARkdGTSSXo3Z63hBsKlhsiIiL8dUv4UY67afVYboiIiAD0u1tu4jNuoprjblo1lhsiIiIAfs42sLc0RXmVCslXC8WOQ83AckNERARAKpWgL28JNwgsN0RERHdx3I1hYLkhIiK6q3bcTcKVW6isUYmchpqK5YaIiOiuDm2t0dZGjsoaNZIyC8WOQ03EckNERHSXRMJxN4aA5YaIiOgemudMcTK/VovlhoiI6B61426SMm/hdhXH3bRGLDdERET3aNfGEq4Kc1SrBCRcuSV2HGoClhsiIqJ7SCSSey5NXRc5DTUFyw0REdHf9O3AQcWtGcsNERHR39SOu0m+WoTSyhqR01BjsdwQERH9jYe9JZQOFqhRC4jLuCl2HGoklhsiIqIH6OXlAAA4lVUobhBqNJYbIiKiB+jqrgAAnM4uEjkJNRbLDRER0QMEetwpN8lXWW5aG5YbIiKiB/B3VUAqAQpKKpFfXCF2HGoElhsiIqIHsDCTwdfJBgCQwrM3rQrLDRER0UN0rb00xXE3rQrLDRER0UNwUHHrxHJDRET0EF3vGVQsCILIaaihWG6IiIgewt/VFjKpBNdLK5HHQcWtBssNERHRQ5ibyuDrZA2Ag4pbE5YbIiKietSOu0nhuJtWg+WGiIioHrWT+bHctB4sN0RERPXo6mEH4M5lKQ4qbh1ELTcrVqxAYGAgbG1tYWtri5CQEOzevfuh669atQoDBw6Evb097O3tERoaitjYWB0mJiIiY9PJxQYmUglulFUhp4iDilsDUcuNh4cHFi1ahISEBMTHx2PIkCEYN24czpw588D1o6OjMWXKFBw4cADHjh2DUqnE8OHDkZ2drePkRERkLMxNZejozJmKWxOJoGfn2BwcHLB48WLMmjXrH9dVqVSwt7fH119/jbCwsAZtv7i4GAqFAkVFRbC1tW1uXCIiMgILNydjQ3wW5j7aAW+O6CR2HKPUmL/fejPmRqVSITIyEmVlZQgJCWnQZ8rLy1FdXQ0HB4eHrlNZWYni4uI6LyIiosboqhlUzL8hrYHo5SYlJQXW1taQy+WYPXs2tm7dCn9//wZ9duHChXBzc0NoaOhD14mIiIBCodC8lEplS0UnIiIjoblj6mohBxW3AqKXGz8/P5w8eRInTpzAnDlzMH36dJw9e/YfP7do0SJERkZi69atMDc3f+h64eHhKCoq0ryysrJaMj4RERkBPxcbmMokuFVejau3bosdh/6BidgBzMzM4OPjAwDo2bMn4uLisHTpUqxcufKhn/n888+xaNEi7Nu3D4GBgfVuXy6XQy6Xt2hmIiIyLnITGfxcbHA6uxins4ugdLAUOxLVQ/QzN3+nVqtRWVn50Pc/++wzfPjhh9izZw+Cg4N1mIyIiIxZ7UzFyZzMT++JeuYmPDwco0aNgqenJ0pKSrB+/XpER0cjKioKABAWFgZ3d3dEREQAAD799FO8++67WL9+Pby8vJCXlwcAsLa2hrW1tWjfBxERGb6u7nb4BVk4zXKj90QtNwUFBQgLC0Nubi4UCgUCAwMRFRWFYcOGAQAyMzMhlf51cmnFihWoqqrCU089VWc77733Ht5//31dRiciIiOjOXNzd6ZiiUQiciJ6GFHLzffff1/v+9HR0XW+zsjI0F4YIiKienR0sYaZTIqi29XIunkbnm047kZf6d2YGyIiIn0kN5Ghk+vdmYp5aUqvsdwQERE1UIBmUHGhuEGoXiw3REREDRR4t9xwULF+Y7khIiJqoIC/DSom/cRyQ0RE1EAdnW1gZiJFSUUNrtwoFzsOPQTLDRERUQOZmUjR2YWDivUdyw0REVEj/PWEcJYbfcVyQ0RE1AiB7nYAgJSrLDf6iuWGiIioEWoHFZ/O4aBifcVyQ0RE1AgdnKwglQAlFTUoKHn4g55JPCw3REREjSA3kcGrjRUA4EJ+qchp6EFYboiIiBrJx8kaAHChoETkJPQgLDdERESN5OtcW2545kYfsdwQERE1kq/TnbluLvKylF5iuSEiImqk2stSaQUlvGNKD7HcEBERNVKHttaQSIDC8mrcKKsSOw79DcsNERFRI1mYyaC0twTAO6b0EcsNERFRE/jevTR1kXdM6R2WGyIioibw4R1TeovlhoiIqAlq75jiZSn9w3JDRETUBL5OPHOjr1huiIiImqD2dvDrpZW4xTum9ArLDRERURNYyU3gbmcBALh4jWdv9AnLDRERURNpHsPAcTd6heWGiIioiXz5AE29xHJDRETURJpnTHFQsV5huSEiImoiH16W0kssN0RERE1Ue8dUXnEFiiuqRU5DtVhuiIiImsjW3BQutuYAeGlKn7DcEBERNUPtHVMXeWlKb7DcEBERNYMP75jSOyw3REREzaB5xhQvS+kNlhsiIqJm4ER++oflhoiIqBl82t4pN9mFt1FaWSNyGgJYboiIiJrF3soMjtZyAMAlXprSCyw3REREzfTXYxhYbvQByw0REVEzacbd8I4pvcByQ0RE1Ey1Z244141+MBE7ABERUWvn63zndvD95wsQ/NE+kdOIL9BDgdUzeom2f5YbIiKiZqo9cwMA10srRUyiHwrLq0TdP8sNERFRM7W5e7cUALzyqA/GBLqKmEZ8FqYyUffPckNERNQCXh3ig6gzeXhhkDcUFqZixzFqog4oXrFiBQIDA2FrawtbW1uEhIRg9+7d9X5m06ZN6NSpE8zNzdG1a1fs2rVLR2mJiIgebsFwP/zx+mAWGz0garnx8PDAokWLkJCQgPj4eAwZMgTjxo3DmTNnHrj+0aNHMWXKFMyaNQtJSUkYP348xo8fj9OnT+s4OREREekriSAIgtgh7uXg4IDFixdj1qxZ9703adIklJWVYceOHZplffv2Rffu3fHNN988cHuVlZWorPxrcFdxcTGUSiWKiopga2vb8t8AERERtbji4mIoFIoG/f3Wm3luVCoVIiMjUVZWhpCQkAeuc+zYMYSGhtZZNmLECBw7duyh242IiIBCodC8lEpli+YmIiIi/SJ6uUlJSYG1tTXkcjlmz56NrVu3wt/f/4Hr5uXlwdnZuc4yZ2dn5OXlPXT74eHhKCoq0ryysrJaND8RERHpF9HvlvLz88PJkydRVFSEzZs3Y/r06YiJiXlowWksuVwOuVz+zysSERGRQRC93JiZmcHHxwcA0LNnT8TFxWHp0qVYuXLlfeu6uLggPz+/zrL8/Hy4uLjoJCsRERHpP9EvS/2dWq2uMwD4XiEhIdi/f3+dZXv37n3oGB0iIiIyPqKeuQkPD8eoUaPg6emJkpISrF+/HtHR0YiKigIAhIWFwd3dHREREQCAefPmYfDgwViyZAnGjBmDyMhIxMfH49tvvxXz2yAiIiI9Imq5KSgoQFhYGHJzc6FQKBAYGIioqCgMGzYMAJCZmQmp9K+TS/369cP69evx9ttv46233oKvry+2bduGgIAAsb4FIiIi0jN6N8+NtjXmPnkiIiLSD61ynhsiIiKilsByQ0RERAaF5YaIiIgMCssNERERGRTRJ/HTtdrx08XFxSInISIiooaq/bvdkPugjK7clJSUAAAfoElERNQKlZSUQKFQ1LuO0d0KrlarkZOTAxsbG0gkkhbddnFxMZRKJbKysoz2NnMegzt4HHgMavE48BjU4nG4o6nHQRAElJSUwM3Nrc4ceA9idGdupFIpPDw8tLoPW1tbo/7BBXgMavE48BjU4nHgMajF43BHU47DP52xqcUBxURERGRQWG6IiIjIoLDctCC5XI733nsPcrlc7Cii4TG4g8eBx6AWjwOPQS0ehzt0cRyMbkAxERERGTaeuSEiIiKDwnJDREREBoXlhoiIiAwKyw0REREZFJabFrJ8+XJ4eXnB3Nwcffr0QWxsrNiRtOrgwYMYO3Ys3NzcIJFIsG3btjrvC4KAd999F66urrCwsEBoaCguXLggTlgtiYiIQK9evWBjYwMnJyeMHz8eqampddapqKjA3Llz0aZNG1hbW2PChAnIz88XKbF2rFixAoGBgZoJuUJCQrB7927N+8ZwDP5u0aJFkEgkmD9/vmaZMRyH999/HxKJpM6rU6dOmveN4RgAQHZ2Np599lm0adMGFhYW6Nq1K+Lj4zXvG8PvRy8vr/t+FiQSCebOnQtA+z8LLDctYMOGDfjXv/6F9957D4mJiejWrRtGjBiBgoICsaNpTVlZGbp164bly5c/8P3PPvsMy5YtwzfffIMTJ07AysoKI0aMQEVFhY6Tak9MTAzmzp2L48ePY+/evaiursbw4cNRVlamWef111/H77//jk2bNiEmJgY5OTl48sknRUzd8jw8PLBo0SIkJCQgPj4eQ4YMwbhx43DmzBkAxnEM7hUXF4eVK1ciMDCwznJjOQ5dunRBbm6u5nX48GHNe8ZwDG7duoX+/fvD1NQUu3fvxtmzZ7FkyRLY29tr1jGG349xcXF1fg727t0LAJg4cSIAHfwsCNRsvXv3FubOnav5WqVSCW5ubkJERISIqXQHgLB161bN12q1WnBxcREWL16sWVZYWCjI5XLhl19+ESGhbhQUFAgAhJiYGEEQ7nzPpqamwqZNmzTrnDt3TgAgHDt2TKyYOmFvby989913RncMSkpKBF9fX2Hv3r3C4MGDhXnz5gmCYDw/C++9957QrVu3B75nLMdg4cKFwoABAx76vrH+fpw3b57QoUMHQa1W6+RngWdumqmqqgoJCQkIDQ3VLJNKpQgNDcWxY8dETCae9PR05OXl1TkmCoUCffr0MehjUlRUBABwcHAAACQkJKC6urrOcejUqRM8PT0N9jioVCpERkairKwMISEhRncM5s6dizFjxtT5fgHj+lm4cOEC3Nzc4O3tjalTpyIzMxOA8RyD7du3Izg4GBMnToSTkxOCgoKwatUqzfvG+PuxqqoK69atw3PPPQeJRKKTnwWWm2a6fv06VCoVnJ2d6yx3dnZGXl6eSKnEVft9G9MxUavVmD9/Pvr374+AgAAAd46DmZkZ7Ozs6qxriMchJSUF1tbWkMvlmD17NrZu3Qp/f3+jOgaRkZFITExERETEfe8Zy3Ho06cP1qxZgz179mDFihVIT0/HwIEDUVJSYjTH4PLly1ixYgV8fX0RFRWFOXPm4LXXXsPatWsBGOfvx23btqGwsBAzZswAoJv/HozuqeBE2jB37lycPn26zvgCY+Ln54eTJ0+iqKgImzdvxvTp0xETEyN2LJ3JysrCvHnzsHfvXpibm4sdRzSjRo3S/DswMBB9+vRBu3btsHHjRlhYWIiYTHfUajWCg4PxySefAACCgoJw+vRpfPPNN5g+fbrI6cTx/fffY9SoUXBzc9PZPnnmppkcHR0hk8nuG+Wdn58PFxcXkVKJq/b7NpZj8sorr2DHjh04cOAAPDw8NMtdXFxQVVWFwsLCOusb4nEwMzODj48PevbsiYiICHTr1g1Lly41mmOQkJCAgoIC9OjRAyYmJjAxMUFMTAyWLVsGExMTODs7G8Vx+Ds7Ozt07NgRFy9eNJqfBVdXV/j7+9dZ1rlzZ83lOWP7/XjlyhXs27cPzz//vGaZLn4WWG6ayczMDD179sT+/fs1y9RqNfbv34+QkBARk4mnffv2cHFxqXNMiouLceLECYM6JoIg4JVXXsHWrVvx559/on379nXe79mzJ0xNTesch9TUVGRmZhrUcXgQtVqNyspKozkGQ4cORUpKCk6ePKl5BQcHY+rUqZp/G8Nx+LvS0lJcunQJrq6uRvOz0L9///umhEhLS0O7du0AGM/vx1o//PADnJycMGbMGM0ynfwstMiwZCMXGRkpyOVyYc2aNcLZs2eFF198UbCzsxPy8vLEjqY1JSUlQlJSkpCUlCQAEL744gshKSlJuHLliiAIgrBo0SLBzs5O+O2334Tk5GRh3LhxQvv27YXbt2+LnLzlzJkzR1AoFEJ0dLSQm5ureZWXl2vWmT17tuDp6Sn8+eefQnx8vBASEiKEhISImLrl/fvf/xZiYmKE9PR0ITk5Wfj3v/8tSCQS4Y8//hAEwTiOwYPce7eUIBjHcViwYIEQHR0tpKenC0eOHBFCQ0MFR0dHoaCgQBAE4zgGsbGxgomJifDxxx8LFy5cEH7++WfB0tJSWLdunWYdY/j9KAh37hz29PQUFi5ceN972v5ZYLlpIV999ZXg6ekpmJmZCb179xaOHz8udiStOnDggADgvtf06dMFQbhzu+M777wjODs7C3K5XBg6dKiQmpoqbugW9qDvH4Dwww8/aNa5ffu28PLLLwv29vaCpaWl8MQTTwi5ubnihdaC5557TmjXrp1gZmYmtG3bVhg6dKim2AiCcRyDB/l7uTGG4zBp0iTB1dVVMDMzE9zd3YVJkyYJFy9e1LxvDMdAEATh999/FwICAgS5XC506tRJ+Pbbb+u8bwy/HwVBEKKiogQAD/zetP2zIBEEQWiZc0BERERE4uOYGyIiIjIoLDdERERkUFhuiIiIyKCw3BAREZFBYbkhIiIig8JyQ0RERAaF5YaIiIgMCssNERERGRSWGyLSqhkzZmD8+PE63++aNWsgkUggkUgwf/78Zm/Lzs6uUZ+ZMWOGZv/btm1r1v6JqHFMxA5ARK2XRCKp9/333nsPS5cuhVgTodva2iI1NRVWVlbN2s6kSZMwevToRn1m6dKlWLRoEVxdXZu1byJqPJYbImqy3Nxczb83bNiAd999t84Tka2trWFtbS1GNAB3ypeLi0uzt2NhYQELC4tGfUahUEChUDR730TUeLwsRURN5uLionkpFApNmah9WVtb33dZ6pFHHsGrr76K+fPnw97eHs7Ozli1ahXKysowc+ZM2NjYwMfHB7t3766zr9OnT2PUqFGwtraGs7Mzpk2bhuvXrzc6s5eXFz766COEhYXB2toa7dq1w/bt23Ht2jWMGzcO1tbWCAwMRHx8vOYzf78s9f7776N79+746aef4OXlBYVCgcmTJ6OkpKTReYio5bHcEJHOrV27Fo6OjoiNjcWrr76KOXPmYOLEiejXrx8SExMxfPhwTJs2DeXl5QCAwsJCDBkyBEFBQYiPj8eePXuQn5+Pp59+ukn7/+9//4v+/fsjKSkJY8aMwbRp0xAWFoZnn30WiYmJ6NChA8LCwuq9nHbp0iVs27YNO3bswI4dOxATE4NFixY1KQ8RtSyWGyLSuW7duuHtt9+Gr68vwsPDYW5uDkdHR7zwwgvw9fXFu+++ixs3biA5ORkA8PXXXyMoKAiffPIJOnXqhKCgIKxevRoHDhxAWlpao/c/evRovPTSS5p9FRcXo1evXpg4cSI6duyIhQsX4ty5c8jPz3/oNtRqNdasWYOAgAAMHDgQ06ZNw/79+5t8TIio5XDMDRHpXGBgoObfMpkMbdq0QdeuXTXLnJ2dAQAFBQUAgFOnTuHAgQMPHL9z6dIldOzYscn7r93Xw/b/sDE7Xl5esLGx0Xzt6uqqyUtE4mK5ISKdMzU1rfO1RCKps6z2Liy1Wg0AKC0txdixY/Hpp5/et62m3I30oH3Vt/9/2kbtZ+pbn4h0h+WGiPRejx49sGXLFnh5ecHEhL+2iKh+HHNDRHpv7ty5uHnzJqZMmYK4uDhcunQJUVFRmDlzJlQqldjxiEjPsNwQkd5zc3PDkSNHoFKpMHz4cHTt2hXz58+HnZ0dpFL+GiOiuiSCWFOHEhFp0Zo1azB//nwUFhaKmkMikWDr1q2iPIKCyFjx//IQkcEqKiqCtbU1Fi5cqPN9z549W9TZmYmMGc/cEJFBKikp0cxTY2dnB0dHR53uv6CgAMXFxQDu3NHV3OdbEVHDsdwQERGRQeFlKSIiIjIoLDdERERkUFhuiIiIyKCw3BAREZFBYbkhIiIig8JyQ0RERAaF5YaIiIgMCssNERERGZT/D2VBAEb4DoNWAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "soln.plot('time_min', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It can also be helpful to extract portions of a `CycleSolution` to examine what occurred within a given step, or to combine `StepSolution` instances so that you can post process or plotting purposes. Both of these features are available, as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "soln_0 = soln.get_steps(0)\n", + "soln_1 = soln.get_steps(1)\n", + "\n", + "soln = thev.CycleSolution(soln_0, soln_1)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_static/api_reference.svg b/docs/source/_static/api_reference.svg new file mode 100644 index 0000000..645d02a --- /dev/null +++ b/docs/source/_static/api_reference.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 0000000..0dffb7b --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,50 @@ +@import "../basic.css"; + +:root { + /* --pst-color-primary: #0079C2 !important; + --pst-color-secondary: #5D9732 !important; */ + + --pst-sidebar-font-size-mobile: 0.9rem !important; +} + +/* Remove caption text on main page, but keep in toc */ +section span.caption-text { + display: none; +} + +/* Fix transparent background in images */ +.transparent { + background: transparent; + background-color: transparent; +} + +/* Dark theme tweaking */ +html[data-theme=dark] .sd-card img[src*='.svg'] { + filter: invert(1.0) brightness(0.8) contrast(1.2); +} + +/* Toggle main page logo for dark/light modes */ +html[data-theme=dark] .ondark { + display: block; +} + +html[data-theme=dark] .onlight { + display: None; +} + +html[data-theme=light] .ondark { + display: None; +} + +html[data-theme=light] .onlight { + display: block; +} + +@media screen and (max-width: 540px) { + h1 {font-size: 30px;} + h2 {font-size: 24px;} + h3 {font-size: 21px;} + h4 {font-size: 18px;} + h5 {font-size: 18px;} + h6 {font-size: 18px;} +} diff --git a/docs/source/_static/custom.js b/docs/source/_static/custom.js new file mode 100644 index 0000000..ec73583 --- /dev/null +++ b/docs/source/_static/custom.js @@ -0,0 +1,17 @@ +document.addEventListener("DOMContentLoaded", function() { + + if (window.navigator.userAgent.indexOf("Mac") != -1) { + document.getElementById("sb-kbd").innerHTML = "Cmd"; + } else { + document.getElementById("sb-kbd").innerHTML = "Ctrl"; + } + +}); + +function removeKBD() { + document.getElementById("sb-kbd-span").style.display = "none"; +} + +function addKBD() { + document.getElementById("sb-kbd-span").style.display = "block"; +} \ No newline at end of file diff --git a/docs/source/_static/dark.png b/docs/source/_static/dark.png new file mode 100644 index 0000000..ff95735 Binary files /dev/null and b/docs/source/_static/dark.png differ diff --git a/docs/source/_static/development.svg b/docs/source/_static/development.svg new file mode 100644 index 0000000..a2e2de5 --- /dev/null +++ b/docs/source/_static/development.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/source/_static/examples.svg b/docs/source/_static/examples.svg new file mode 100644 index 0000000..d4ad768 --- /dev/null +++ b/docs/source/_static/examples.svg @@ -0,0 +1,51 @@ + + + + + + + + + + diff --git a/docs/source/_static/favicon.ico b/docs/source/_static/favicon.ico new file mode 100644 index 0000000..8f0a623 Binary files /dev/null and b/docs/source/_static/favicon.ico differ diff --git a/docs/source/_static/icons.svg b/docs/source/_static/icons.svg new file mode 100644 index 0000000..2b0228c --- /dev/null +++ b/docs/source/_static/icons.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/_static/light.png b/docs/source/_static/light.png new file mode 100644 index 0000000..ca60545 Binary files /dev/null and b/docs/source/_static/light.png differ diff --git a/docs/source/_static/user_guide.svg b/docs/source/_static/user_guide.svg new file mode 100644 index 0000000..928fa99 --- /dev/null +++ b/docs/source/_static/user_guide.svg @@ -0,0 +1,50 @@ + + + + + + + + + + diff --git a/docs/source/_templates/navbar-logo.html b/docs/source/_templates/navbar-logo.html new file mode 100644 index 0000000..bf0c3b0 --- /dev/null +++ b/docs/source/_templates/navbar-logo.html @@ -0,0 +1,37 @@ +{# Displays the logo of your documentation site, in the header navbar. #} +{# Logo link generation -#} +{% if theme_logo_link %} + {% set href = theme_logo_link %} +{% else %} + {% if not theme_logo.get("link") %} + {% set href = pathto(root_doc) %} + {% elif hasdoc(theme_logo.get("link")) %} + {% set href = pathto(theme_logo.get("link")) %} {# internal page #} + {% else %} + {% set href = theme_logo.get("link") %} {# external url #} + {% endif %} +{% endif %} + +{#- Logo HTML and image #} + \ No newline at end of file diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst new file mode 100644 index 0000000..bb8d98a --- /dev/null +++ b/docs/source/api/index.rst @@ -0,0 +1,11 @@ +API Reference +============= + +This page contains auto-generated API reference documentation [#f1]_. + +.. toctree:: + :titlesonly: + + /api/thevenin/index + +.. [#f1] Created with `sphinx-autoapi `_ \ No newline at end of file diff --git a/docs/source/api/thevenin/index.rst b/docs/source/api/thevenin/index.rst new file mode 100644 index 0000000..9befcdb --- /dev/null +++ b/docs/source/api/thevenin/index.rst @@ -0,0 +1,698 @@ +thevenin +======== + +.. py:module:: thevenin + +.. autoapi-nested-parse:: + + .. rubric:: Summary + + The Thevenin equivalent circuit model is a common low-fidelity battery model + consisting of a single resistor in series with any number of RC pairs, i.e., + parallel resistor-capacitor pairs. This Python package contains an API for + building and running experiments using Thevenin models. When referring to the + model itself, we use capitalized "Thevenin", and for the package lowercase + ``thevenin``. + + .. rubric:: Accessing the Documentation + + Documentation is accessible via Python's ``help()`` function which prints + docstrings from a package, module, function, class, etc. You can also access + the documentation by visiting the website, hosted on Read the Docs. The website + includes search functionality and more detailed examples. + + + +Subpackages +----------- + +.. toctree:: + :maxdepth: 1 + + /api/thevenin/loadfns/index + /api/thevenin/plotutils/index + + +Classes +------- + +.. autoapisummary:: + + thevenin.CycleSolution + thevenin.Experiment + thevenin.IDASolver + thevenin.Model + thevenin.StepSolution + + +Package Contents +---------------- + +.. py:class:: CycleSolution(*soln) + + + + All-step solution. + + A solution instance with all experiment steps stitch together into + a single cycle. + + :param \*soln: All unpacked StepSolution instances to stitch together. The given + steps should be given in the same sequential order that they were + run. + :type \*soln: StepSolution + + + .. py:method:: get_steps(idx) + + Return a subset of the solution. + + :param idx: The step index (int) or first/last indices (tuple) to return. + :type idx: int | tuple + + :returns: **soln** (*StepSolution | CycleSolution*) -- The returned solution subset. A StepSolution is returned if 'idx' + is an int, and a CycleSolution will be returned for the range of + requested steps when 'idx' is a tuple. + + + + .. py:method:: plot(x, y, **kwargs) + + Plot any two variables in 'vars' against each other. + + :param x: A variable key in 'vars' to be used for the x-axis. + :type x: str + :param y: A variable key in 'vars' to be used for the y-axis. + :type y: str + + :returns: *None.* + + + + .. py:property:: solvetime + :type: str + + Print a statement specifying how long IDASolver spent integrating. + + :returns: **solvetime** (*str*) -- An f-string with the total solver integration time in seconds. + + +.. py:class:: Experiment(**kwargs) + + Experiment builder. + + A class to define an experimental protocol. Use the add_step() method + to add a series of sequential steps. Each step defines a control mode, + a constant or time-dependent load profile, a time span, and optional + limiting criteria to stop the step early if a specified event/state is + detected. + + :param kwargs: IDASolver keyword arguments that will span all steps. + :type kwargs: dict, optional + + .. seealso:: + + :obj:`~thevenin.IDASolver` + The solver class, with documentation for most keyword arguments that you might want to adjust. + + + .. py:method:: add_step(mode, value, tspan, limits = None, **kwargs) + + Add a step to the experiment. + + :param mode: Control mode, from {'current_A', 'voltage_V', 'power_W'}. + :type mode: str + :param value: Value of boundary contion in the appropriate units. + :type value: float | Callable + :param tspan: Relative times for recording solution [s]. Providing a tuple as + (t_max: float, Nt: int) or (t_max: float, dt: float) constructs + tspan using ``np.linspace`` or ``np.arange``, respectively. See + the notes for more information. + :type tspan: tuple + :param limits: Stopping criteria for the new step, must be entered in sequential + name/value pairs. Allowable names are {'soc', 'temperature_K', + 'current_A', 'voltage_V', 'power_W', 'capacity_Ah', 'time_s', + 'time_min', 'time_h'}. Values for each limit should immediately + follow a corresponding name and be the appropriate units. All of + the time limits represent the total experiment time. The default + is None. + :type limits: tuple[str, float], optional + :param \*\*kwargs: IDASolver keyword arguments specific to the new step only. + :type \*\*kwargs: dict, optional + + :returns: *None.* + + :raises ValueError: 'mode' is invalid. + :raises ValueError: A 'limits' name is invalid. + :raises ValueError: 'tspan' tuple must be length 2. + :raises TypeError: 'tspan[1]' must be type int or float. + + .. seealso:: + + :obj:`~thevenin.IDASolver` + The solver class, with documentation for most keyword arguments that you might want to adjust. + + .. rubric:: Notes + + For time-dependent loads, use a Callable for 'value' with a function + signature like def load(t: float) -> float, where t is the step's + relative time, in seconds. + + The solution times array is constructed depending on the 'tspan' + input types: + + * Given (float, int): + ``tspan = np.linspace(0., tspan[0], tspan[1])`` + * Given (float, float): + ``tspan = np.arange(0., tspan[0], tspan[1])`` + + In this case, 't_max' is also appended to the end. This results + in the final 'dt' being different from the others if 't_max' is + not evenly divisible by the given 'dt'. + + + + .. py:method:: print_steps() + + Prints a formatted/readable list of steps. + + :returns: *None.* + + + + .. py:property:: num_steps + :type: int + + Return number of steps. + + :returns: **num_steps** (*int*) -- Number of steps. + + + .. py:property:: steps + :type: list[dict] + + Return steps list. + + :returns: **steps** (*list[dict]*) -- List of the step dictionaries. + + +.. py:class:: IDASolver(resfn, **options) + + + + SUNDIALS IDA solver. + + This class wraps the implicit differential algebraic (IDA) solver from + SUNDIALS. It can be used to solve both ordinary differential equations + (ODEs) and differiential agebraic equatinos (DAEs). + + :param resfn: Residual function with signature ``f(t, y, yp, res[, userdata])``. + If 'resfn' has return values, they are ignored. Instead of using + returns, the solver interacts directly with the 'res' array memory. + For more info see the notes. + :type resfn: Callable + :param \*\*options: Keyword arguments to describe the solver options. A full list of + names, types, descriptions, and defaults is given below. + :type \*\*options: dict, optional + :param userdata: Additional data object to supply to all user-defined callables. If + 'resfn' takes in 5 arguments, including the optional 'userdata', + then this option cannot be None (default). See notes for more info. + :type userdata: object or None, optional + :param calc_initcond: Specifies which initial condition, if any, to calculate prior to + the first time step. The options 'y0' and 'yp0' will correct 'y0' + or 'yp0' values at 't0', respectively. When not None (default), + the 'calc_init_dt' value should be used to specify the direction + of integration. + :type calc_initcond: {'y0', 'yp0', None}, optional + :param calc_init_dt: Relative time step to take during the initial condition correction. + Positive vs. negative values provide the direction of integration + as forwards or backwards, respectively. The default is 0.01. + :type calc_init_dt: float, optional + :param algebraic_idx: Specifies indices 'i' in the 'y[i]' state variable array that are + purely algebraic. This option should always be provided for DAEs; + otherwise, the solver can be unstable. The default is None. + :type algebraic_idx: array_like[int] or None, optional + :param first_step: Specifies the initial step size. The default is 0, which uses an + estimated value internally determined by SUNDIALS. + :type first_step: float, optional + :param min_step: Minimum allowable step size. The default is 0. + :type min_step: float, optional + :param max_step: Maximum allowable step size. Use 0 (default) for unbounded steps. + :type max_step: float, optional + :param rtol: Relative tolerance. For example, 1e-4 means errors are controlled + to within 0.01%. It is recommended to not use values larger than + 1e-3 nor smaller than 1e-15. The default is 1e-5. + :type rtol: float, optional + :param atol: Absolute tolerance. Can be a scalar float to apply the same value + for all state variables, or an array with a length matching 'y' to + provide tolerances specific to each variable. The default is 1e-6. + :type atol: float or array_like[float], optional + :param linsolver: Choice of linear solver. When using 'band', don't forget to provide + 'lband' and 'uband' values. The default is 'dense'. + :type linsolver: {'dense', 'band'}, optional + :param lband: Lower Jacobian bandwidth. Given a DAE system ``0 = F(t, y, yp)``, + the Jacobian is ``J = dF_i/dy_j + c_j*dF_i/dyp_j`` where 'c_j' is + determined internally based on both step size and order. 'lband' + should be set to the max distance between the main diagonal and the + non-zero elements below the diagonal. This option cannot be None + (default) if 'linsolver' is 'band'. Use zero if no values are below + the main diagonal. + :type lband: int or None, optional + :param uband: Upper Jacobian bandwidth. See 'lband' for the Jacobian description. + 'uband' should be set to the max distance between the main diagonal + and the non-zero elements above the diagonal. This option cannot be + None (default) if 'linsolver' is 'band'. Use zero if no elements + are above the main diagonal. + :type uband: int or None, optional + :param max_order: Specifies the maximum order for the linear multistep BDF method. + The value must be in the range [1, 5]. The default is 5. + :type max_order: int, optional + :param max_num_steps: Specifies the maximum number of steps taken by the solver in each + attempt to reach the next output time. The default is 500. + :type max_num_steps: int, optional + :param max_nonlin_iters: Specifies the maximum number of nonlinear solver iterations in one + step. The default is 4. + :type max_nonlin_iters: int, optional + :param max_conv_fails: Specifies the max number of nonlinear solver convergence failures + in one step. The default is 10. + :type max_conv_fails: int, optional + :param constraints_idx: Specifies indices 'i' in the 'y' state variable array for which + inequality constraints should be applied. Constraints types must be + specified in 'constraints_type', see below. The default is None. + :type constraints_idx: array_like[int] or None, optional + :param constraints_type: If 'constraints_idx' is not None, then this option must include an + array of equal length specifying the types of constraints to apply. + Values should be in ``{-2, -1, 1, 2}`` which apply ``y[i] < 0``, + ``y[i] <= 0``, ``y[i] >=0,`` and ``y[i] > 0``, respectively. The + default is None. + :type constraints_type: array_like[int] or None, optional + :param eventsfn: Events function with signature ``g(t, y, yp, events[, userdata])``. + Return values from this function are ignored. Instead, the solver + directly interacts with the 'events' array. Each 'events[i]' should + be an expression that triggers an event when equal to zero. If None + (default), no events are tracked. See the notes for more info. + + The 'num_events' option is required when 'eventsfn' is not None so + memory can be allocated for the events array. The events function + can also have the following attributes: + + terminal: list[bool, int], optional + A list with length 'num_events' that tells how the solver + how to respond to each event. If boolean, the solver will + terminate when True and will simply record the event when + False. If integer, termination occurs at the given number + of occurrences. The default is ``[True]*num_events``. + direction: list[int], optional + A list with length 'num_events' that tells the solver which + event directions to track. Values must be in ``{-1, 0, 1}``. + Negative values will only trigger events when the slope is + negative (i.e., 'events[i]' went from positive to negative). + Alternatively, positive values track events with positive + slope. If zero, either direction triggers the event. When + not assigned, ``direction = [0]*num_events``. + + You can assign attributes like ``eventsfn.terminal = [True]`` to + any function in Python, after it has been defined. + :type eventsfn: Callable or None, optional + :param num_events: Number of events to track. Must be greater than zero if 'eventsfn' + is not None. The default is 0. + :type num_events: int, optional + :param jacfn: Jacobian function like ``J(t, y, yp, res, cj, JJ[, userdata])``. + The function should fill the pre-allocated 2D matrix 'JJ' with the + values defined by ``JJ[i,j] = dres_i/dy_j + cj*dres_i/dyp_j``. An + internal finite difference method is applied when None (default). + As with other user-defined callables, return values from 'jacfn' + are ignored. See notes for more info. + :type jacfn: Callable or None, optional + + .. rubric:: Notes + + Return values from 'resfn', 'eventsfn', and 'jacfn' are ignored by the + solver. Instead the solver directly reads from pre-allocated memory. + The 'res', 'events', and 'JJ' arrays from each user-defined callable + should be filled within each respective function. When setting values + across the entire array/matrix at once, don't forget to use ``[:]`` to + fill the existing array rather than overwriting it. For example, using + ``res[:] = F(t, y, yp)`` is correct whereas ``res = F(t, y, yp)`` is + not. Using this method of pre-allocated memory helps pass data between + Python and the SUNDIALS C functions. It also keeps the solver fast, + especially for large problems. + + When 'resfn' (or 'eventsfn', or 'jacfn') require data outside of their + normal arguments, you can supply 'userdata' as an option. When given, + 'userdata' must appear in the function signatures for ALL of 'resfn', + 'eventsfn' (when not None), and 'jacfn' (when not None), even if it is + not used in all of these functions. Note that 'userdata' only takes up + one argument position; however, 'userdata' can be any Python object. + Therefore, to pass more than one extra argument you should pack all of + the data into a single tuple, dict, dataclass, etc. and pass them all + together as 'userdata'. The data can be unpacked as needed within a + function. + + .. rubric:: Examples + + The following example solves the Robertson problem, which is a classic + test problem for programs that solve stiff ODEs. A full description of + the problem is provided by `MATLAB`_. Note that while initializing the + solver, ``algebraic_idx=[2]`` specifies ``y[2]`` is purely algebraic, + and ``calc_initcond='yp0'`` tells the solver to determine the values + for 'yp0' at 'tspan[0]' before starting to integrate. That is why 'yp0' + can be initialized as an array of zeros even though plugging in 'y0' + to the residuals expressions actually gives ``yp0 = [-0.04, 0.04, 0]``. + The initialization is checked against the correct answer after solving. + + .. _MATLAB: + https://mathworks.com/help/matlab/math/ + solve-differential-algebraic-equations-daes.html + + .. code-block:: python + + import numpy as np + import sksundae as sun + import matplotlib.pyplot as plt + + def resfn(t, y, yp, res): + res[0] = yp[0] + 0.04*y[0] - 1e4*y[1]*y[2] + res[1] = yp[1] - 0.04*y[0] + 1e4*y[1]*y[2] + 3e7*y[1]**2 + res[2] = y[0] + y[1] + y[2] - 1.0 + + solver = sun.ida.IDA(resfn, algebraic_idx=[2], calc_initcond='yp0') + + tspan = np.hstack([0, 4*np.logspace(-6, 6)]) + y0 = np.array([1, 0, 0]) + yp0 = np.zeros_like(y0) + + soln = solver.solve(tspan, y0, yp0) + assert np.allclose(soln.yp[0], [-0.04, 0.04, 0], rtol=1e-3) + + soln.y[:, 1] *= 1e4 # scale y[1] so it is visible in the figure + plt.semilogx(soln.t, soln.y) + plt.show() + + + .. py:method:: init_step(t0, y0, yp0) + + Initialize the solver. + + This method is called automatically when using 'solve'. However, it + must be run manually, before the 'step' method, when solving with a + step-by-step approach. + + :param t0: Initial value of time. + :type t0: float + :param y0: State variable values at 't0'. The length must match that of 'yp0' + and the number of residual equations in 'resfn'. + :type y0: array_like[float], shape(m,) + :param yp0: Time derivatives for the 'y0' array, evaluated at 't0'. The length + and indexing should be consistent with 'y0'. + :type yp0: array_like[float], shape(m,) + + :returns: :class:`~sksundae.ida.IDAResult` -- Custom output class for IDA solutions. Includes pretty-printing + consistent with scipy outputs. See the class definition for more + information. + + :raises MemoryError: Failed to allocate memory for the IDA solver. + :raises RuntimeError: A SUNDIALS function returned NULL or was unsuccessful. + :raises ValueError: 'y0' and 'yp0' must be the same length. + + + + .. py:method:: solve(tspan, y0, yp0) + + Return the solution across 'tspan'. + + :param tspan: Solution time span. If ``len(tspan) == 2``, the solution will be + saved at internally chosen steps. When ``len(tspan) > 2``, the + solution saves the output at each specified time. + :type tspan: array_like[float], shape(n >= 2,) + :param y0: State variable values at 'tspan[0]'. The length must match that of + 'yp0' and the number of residual equations in 'resfn'. + :type y0: array_like[float], shape(m,) + :param yp0: Time derivatives for the 'y0' array, evaluated at 'tspan[0]'. The + length and indexing should be consistent with 'y0'. + :type yp0: array_like[float], shape(m,) + + :returns: :class:`~sksundae.ida.IDAResult` -- Custom output class for IDA solutions. Includes pretty-printing + consistent with scipy outputs. See the class definition for more + information. + + :raises ValueError: 'tspan' must be strictly increasing or decreasing. + :raises ValueError: 'tspan' length must be >= 2. + + + + .. py:method:: step(t, method='normal', tstop=None) + + Return the solution at time 't'. + + Before calling the 'step' method, you must first initialize the solver + by running 'init_step'. + + :param t: Value of time. + :type t: float + :param method: Solve method for the current step. When 'normal' (default), output + is returned at time 't'. If 'onestep', output is returned after one + internal step toward 't'. Both methods stop at events, if given, + regardless of how 'eventsfn.terminal' was set. + :type method: {'normal', 'onestep'}, optional + :param tstop: Specifies a hard time constraint for which the solver should not + pass, regardless of the 'method'. The default is None. + :type tstop: float, optional + + :returns: :class:`~sksundae.ida.IDAResult` -- Custom output class for IDA solutions. Includes pretty-printing + consistent with scipy outputs. See the class definition for more + information. + + :raises ValueError: 'method' value is invalid. Must be 'normal' or 'onestep'. + :raises ValueError: 'init_step' must be run prior to 'step'. + + .. rubric:: Notes + + In general, when solving step by step, times should all be provided in + either increasing or decreasing order. The solver can output results at + times taken in the opposite direction of integration if the requested + time is within the last internal step interval; however, values outside + this interval will raise errors. Rather than trying to mix forward and + reverse directions, choose each sequential time step carefully so you + get all of the values you need. + + SUNDIALS provides a convenient graphic to help users understand how the + step method and optional 'tstop' affect where the integrator stops. To + read more, see their documentation `here`_. + + .. _here: https://computing.llnl.gov/projects/sundials/usage-notes + + + +.. py:class:: Model(params = 'params.yaml') + + Circuit model. + + A class to construct and run the model. Provide the parameters using + either a dictionary or a '.yaml' file. Note that the number of Rj and + Cj attributes must be consistent with the num_RC_pairs value. See the + notes for more information on the callable parameters. + + :param params: Mapping of model parameter names to their values. Can be either + a dict or absolute/relateive file path to a yaml file (str). The + keys/value pair descriptions are given below. The default uses a + .yaml file. Use the templates() function to view this file. + + ============= ========================================= + Key Value (*type*, units) + ============= ========================================= + num_RC_pairs number of RC pairs (*int*, -) + soc0 initial state of charge (*float*, -) + capacity maximum battery capacity (*float*, Ah) + mass total battery mass (*float*, kg) + isothermal flag for isothermal model (*bool*, -) + Cp specific heat capacity (*float*, J/kg/K) + T_inf room/air temperature (*float*, K) + h_therm convective coefficient (*float*, W/m2/K) + A_therm heat loss area (*float*, m2) + ocv open circuit voltage (*callable*, V) + R0 series resistance (*callable*, Ohm) + Rj resistance in RCj (*callable*, Ohm) + Cj capacity in RCj (*callable*, F) + ============= ========================================= + :type params: dict | str + + :raises TypeError: 'params' must be type dict or str. + :raises ValueError: 'params' contains invalid and/or excess key/value pairs. + + .. warning:: + + A pre-processor runs at the end of the model initialization. If you + modify any parameters after class instantiation, you will need to + manually re-run the pre-processor (i.e., the pre() method) afterward. + + .. rubric:: Notes + + The ocv property should have a signature like f(soc: float) -> float, + where soc is the time-dependent state of charged solved for within + the model. All R0, Rj, and Cj properties should have signatures like + f(soc: float, T_cell: float) -> float, where T_cell is the temperature + in K determined in the model. + + Rj and Cj are not true property names. These are just used generally + in the documentation. If num_RC_pairs=1 then in addition to R0, you + should define R1 and C1. If num_RC_pairs=2 then you should also give + values for R2 and C2, etc. For the special case where num_RC_pairs=0, + you should not provide any resistance or capacitance values besides + the series resistance R0, which is always required. + + + .. py:method:: pre() + + Pre-process and prepare the model for running experiments. + + This method builds solution pointers, registers algebraic variable + indices, stores the mass matrix, and initializes the battery state. + + :returns: *None.* + + .. warning:: + + This method runs the first time during the class initialization. It + generally does not have to be run again unless you modify any model + attributes. You should manually re-run the pre-processor if you alter + any properties after initialization. Forgetting to manually re-run the + pre-processor may cause inconsistencies between the updated properties + and the model's pointers, state, etc. + + + + .. py:method:: residuals(t, sv, svdot, inputs) + + Return the DAE residuals. + + The DAE residuals should be near zero at each time step. The solver + requires the DAE to be written in terms of its residuals in order to + minimize their values. + + :param t: Value of time [s]. + :type t: float + :param sv: State variables at time t. + :type sv: 1D np.array + :param svdot: State variable time derivatives at time t. + :type svdot: 1D np.array + :param inputs: Dictionary detailing an experimental step. + :type inputs: dict + + :returns: **res** (*1D np.array*) -- DAE residuals, res = M*yp - rhs(t, y). + + + + .. py:method:: rhs_funcs(t, sv, inputs) + + Right hand side functions. + + Returns the right hand side for the DAE system. For any differential + variable i, rhs[i] must be equivalent to M[i, i]*y[i]. For algebraic + variables rhs[i] must be an expression that equals zero. + + :param t: Value of time [s]. + :type t: float + :param sv: State variables at time t. + :type sv: 1D np.array + :param inputs: Dictionary detailing an experimental step. + :type inputs: dict + + :returns: **rhs** (*1D np.array*) -- The right hand side values of the DAE system. + + + + .. py:method:: run(exp) + + Run an experiment. + + :param exp: An experiment instance. + :type exp: Experiment + + :returns: **soln** (*CycleSolution*) -- A stitched solution will all experimental steps. + + .. seealso:: + + :obj:`Experiment` + Build an experiment. + + :obj:`CycleSolution` + Wrapper for an all-steps solution. + + + + .. py:method:: run_step(exp, stepidx) + + Run a single experimental step. + + :param exp: An experiment instance. + :type exp: Experiment + :param stepidx: Step index to run. The first step has index 0. + :type stepidx: int + + :returns: **soln** (*StepSolution*) -- Solution to the experiment step. + + .. warning:: + + The model's internal state is changed at the end of each experiment + step. Consequently, you should not run steps out of order. You should + always start with ``stepidx = 0`` and then progress to the subsequent + steps afterward. After the last step, you should manually run the + preprocessor ``pre()`` to reset the model before running additional + experiments. + + .. seealso:: + + :obj:`Experiment` + Build an experiment. + + :obj:`StepSolution` + Wrapper for a single-step solution. + + .. rubric:: Notes + + Using the ``run()`` method will automatically run all steps in an + experiment and will stitch the solutions together for you. You should + only run step by step if you trying to fine tune solver options, or + if you have a complex protocol and you can't set an experimental step + until interpreting a previous step. + + + +.. py:class:: StepSolution(model, ida_soln, timer) + + + + Single-step solution. + + A solution instance for a single experimental step. + + :param model: The model instance that was run to produce the solution. + :type model: Model + :param ida_soln: The unformatted solution returned by IDASolver. + :type ida_soln: SolverReturn + :param timer: Amount of time it took for IDASolver to perform the integration. + :type timer: float + + + .. py:method:: plot(x, y, **kwargs) + + Plot any two variables in 'vars' against each other. + + :param x: A variable key in 'vars' to be used for the x-axis. + :type x: str + :param y: A variable key in 'vars' to be used for the y-axis. + :type y: str + + :returns: *None.* + + + + .. py:property:: solvetime + :type: str + + Print a statement specifying how long IDASolver spent integrating. + + :returns: **solvetime** (*str*) -- An f-string with the solver integration time in seconds. + + diff --git a/docs/source/api/thevenin/loadfns/index.rst b/docs/source/api/thevenin/loadfns/index.rst new file mode 100644 index 0000000..d4f1a19 --- /dev/null +++ b/docs/source/api/thevenin/loadfns/index.rst @@ -0,0 +1,149 @@ +thevenin.loadfns +================ + +.. py:module:: thevenin.loadfns + +.. autoapi-nested-parse:: + + Load Functions + -------------- + This module contains classes to help construct time-varying load profiles. + All of the classes are callable after construction and take in a value of + time in seconds. Most load functions include a linear ramp that "smooths" + transitions from rest to a constant load, or between constant steps. Using + ramps helps the solver maintain stability when a boundary condition sharply + changes from one value to another, e.g., jumping from rest into a high-rate + charge or discharge. For example, in some cases the solver may crash for a + high-rate discharge. + + + +Classes +------- + +.. autoapisummary:: + + thevenin.loadfns.Ramp + thevenin.loadfns.Ramp2Constant + thevenin.loadfns.RampedSteps + thevenin.loadfns.StepFunction + + +Package Contents +---------------- + +.. py:class:: Ramp(m, b = 0.0) + + Linearly ramping load. + + A load profile that continuously ramps with slope m. + + :param m: Slope [units/s]. + :type m: float + :param b: Y-intercept [units]. The default is 0. + :type b: float, optional + + +.. py:class:: Ramp2Constant(m, step, b = 0.0, sharpness = 100.0) + + Ramp to a constant load. + + A load profile that ramps with slope m unil the constant step value + is reached, after which, the load is equal to the step constant. A + sigmoid is used to smooth the transition between the two piecewise + functions. Use a large 'sharpness' to reduce smoothing effects. + + :param m: Slope [units/s]. + :type m: float + :param step: Constant step value [units]. + :type step: float + :param b: Y-intercept [units]. The default is 0. + :type b: float, optional + :param sharpness: How sharp to make the transition between the ramp and step. Low + values will smooth the transition more. The default is 100. + :type sharpness: float, optional + + :raises ValueError: m = 0. and m = inf are invalid slopes. + :raises ValueError: Cannot reach step with m > 0. and b >= step. + :raises ValueError: Cannot reach step with m < 0. and b <= step. + :raises ValueError: 'sharpness' must be strictly positive. + + +.. py:class:: RampedSteps(tp, yp, t_ramp, y0 = 0.0) + + Step function with ramps. + + This class acts like StepFunction, with the same tp, yp, and y0, but + step transitions include ramps with duration t_ramp. Generally, this + profile will be more stable compared to a StepFunction profile. + + :param tp: Times at which a step change occurs [seconds]. + :type tp: 1D np.array + :param yp: Constant values for each time interval. + :type yp: 1D np.array + :param t_ramp: Ramping time between step transitions [seconds]. + :type t_ramp: float + :param y0: Value to return when t < tp[0]. In addition to standard float + values, np.nan and np.inf are supported. The default is 0. + :type y0: float + + :raises ValueError: tp and yp must both be 1D. + :raises ValueError: tp and yp must be same size. + :raises ValueError: t_ramp must be strictly positive. + :raises ValueError: tp must be strictly increasing. + + .. seealso:: + + :obj:`StepFunction` + Uses hard discontinuous steps rather than ramped steps. Generally non-ideal for simulations, but may be useful elsewhere. + + +.. py:class:: StepFunction(tp, yp, y0 = 0.0, ignore_nan = False) + + Piecewise step function. + + Construct a piecewise step function given the times at which step + changes occur and the values for each time interval. For example, + + .. code-block:: python + + tp = np.array([0, 5]) + yp = np.array([-1, 1]) + + y = StepFunction(tp, yp, np.nan) + + Corresponds to + + .. code-block:: python + + if t < 0: + y = np.nan + elif 0 <= t < 5: + y = -1 + else: + y = 1 + + :param tp: Times at which a step change occurs [s]. + :type tp: 1D np.array + :param yp: Constant values for each time interval. + :type yp: 1D np.array + :param y0: Value to return when t < tp[0]. In addition to standard float + values, np.nan and np.inf are supported. The default is 0. + :type y0: float, optional + :param ignore_nan: Whether or not to ignore NaN inputs. For NaN inputs, the callable + returns NaN when False (default) or yp[-1] when True. + :type ignore_nan: bool, optional + + :raises ValueError: tp and yp must both be 1D. + :raises ValueError: tp and yp must be same size. + :raises ValueError: tp must be strictly increasing. + + .. rubric:: Examples + + >>> tp = np.array([0, 1, 5]) + >>> yp = np.array([-1, 0, 1]) + >>> func = StepFunction(tp, yp, np.nan) + >>> print(func(np.array([-10, 0.5, 4, 10]))) + [nan -1. 0. 1.] + + diff --git a/docs/source/api/thevenin/plotutils/index.rst b/docs/source/api/thevenin/plotutils/index.rst new file mode 100644 index 0000000..5a61de4 --- /dev/null +++ b/docs/source/api/thevenin/plotutils/index.rst @@ -0,0 +1,55 @@ +thevenin.plotutils +================== + +.. py:module:: thevenin.plotutils + +.. autoapi-nested-parse:: + + Plotting Utilities + ------------------ + A module designed to enhance plotting with the matplotlib library. Helper + functions include routines for simplifying color scheme management, formatting + axis ticks, fonts, and more, making it easier to create polished and consistent + visualizations. + + + +Functions +--------- + +.. autoapisummary:: + + thevenin.plotutils.get_colors + + +Package Contents +---------------- + +.. py:function:: get_colors(size, data = None, norm = None, alpha = 1.0, cmap = 'jet') + + Sample colors from 'cmap'. + + Return a list of colors from a specified colormap. Default options will + provide evenly spaced colors across 'cmap'. Provide 'data' and/or 'norm' + to control the ordering, spacing, and normalization. + + :param size: Number of colors to return. + :type size: int + :param data: A 1D array with length 'size' that controls the spacing and sorting of + the output. By default, spacing is equal and sorting matches 'cmap'. + :type data: array_like[float] or None, optional + :param norm: An array-like (min, max) pair that normalizes the colormap to 'data'. + By default (0, size) if 'data=None' or min/max of 'data' otherwise. + :type norm: array_like[float] or None, optional + :param alpha: Transparency to apply over the colormap. Must be in the range [0, 1]. + The default is 1. + :type alpha: float, optional + :param cmap: A valid matplotlib colormap name. The default is 'jet'. + :type cmap: str, optional + + :returns: **colors** (*list*) -- A list of (r, g, b, a) color codes. + + :raises ValueError: 'data' length must match 'size'. + :raises ValueError: 'norm' length must equal 2. + + diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..b64b4ab --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,134 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import thevenin as thev # codespell:ignore thev + +project = 'thevenin' +copyright = '2024, Corey R. Randall' +author = 'Corey R. Randall' +version = thev.__version__ # codespell:ignore thev +release = thev.__version__ # codespell:ignore thev + + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.todo', + 'sphinx.ext.viewcode', + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'autoapi.extension', + 'myst_nb', + 'sphinx_design', + # 'sphinx_favicon', + 'sphinx_copybutton', +] + +templates_path = ['_templates'] + +exclude_patterns = [ + 'build', + 'Thumbs.db', + '.DS_Store', + '*.ipynb_checkpoints', + '__pycache__', +] + +source_suffix = { + '.rst': 'restructuredtext', + '.ipynb': 'myst-nb', + '.myst': 'myst-nb', +} + +highlight_language = 'console' + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +# https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/layout.html + +html_theme = 'pydata_sphinx_theme' + +# html_favicon = 'static/favicon.ico' +html_context = {'default_mode': 'dark'} + +html_static_path = ['_static'] +html_js_files = ['custom.js'] +html_css_files = ['custom.css'] + +html_sidebars = {'index': [], '**': ['sidebar-nav-bs']} + +html_theme_options = { + # 'logo': { + # 'image_light': 'static/light.png', + # 'image_dark': 'static/dark.png' + # }, + 'icon_links': [ + { + 'name': 'GitHub', + 'url': 'https://github.com/NREL/thevenin', + 'icon': 'fa-brands fa-github', + }, + # { + # 'name': 'PyPI', + # 'url': 'https://pypi.org/project/thevenin', + # 'icon': 'fa-solid fa-box', + # }, + ], + 'navbar_start': ['navbar-logo'], + 'navbar_align': 'content', + 'header_links_before_dropdown': 5, + 'footer_start': ['copyright'], + 'footer_end': ['sphinx-version'], + 'navbar_persistent': ['search-button-field'], + 'primary_sidebar_end': ['sidebar-ethical-ads'], + 'secondary_sidebar_items': ['page-toc'], + 'search_bar_text': 'Search...', + 'show_prev_next': False, + 'collapse_navigation': True, + 'show_toc_level': 0, + 'pygments_light_style': 'tango', +} + +# -- Options for napoleon ---------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html + +napoleon_use_rtype = False +napoleon_custom_sections = [ + "Summary", + "Accessing the documentation", +] + + +# -- Options for autoapi ----------------------------------------------------- +# https://sphinx-autoapi.readthedocs.io/en/latest/reference/config.html + +autoapi_type = 'python' +autoapi_ignore = ['*/__pycache__/*'] +autoapi_dirs = ['../../src/thevenin'] +autoapi_keep_files = True +autoapi_root = 'api' +autoapi_member_order = 'groupwise' +autodoc_typehints = 'none' +autoapi_python_class_content = 'both' +autoapi_options = [ + 'members', + 'inherited-members', + 'undoc-members', + 'show-module-summary', + 'imported-members', +] + + +# -- Options for myst -------------------------------------------------------- +# https://myst-nb.readthedocs.io/en/latest/configuration.html + +nb_execution_timeout = 300 +nb_number_source_lines = True +myst_enable_extensions = ['amsmath', 'dollarmath'] diff --git a/docs/source/development/code_of_conduct.rst b/docs/source/development/code_of_conduct.rst new file mode 100644 index 0000000..29ccebe --- /dev/null +++ b/docs/source/development/code_of_conduct.rst @@ -0,0 +1,114 @@ +Code of Conduct +=============== + +Our Pledge +---------- +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socioeconomic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +Our Standards +------------- +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +Scope +----- +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +Enforcement +----------- +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +corey.randall@nrel.gov. All complaints will be reviewed and investigated promptly +and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +Enforcement Guidelines +^^^^^^^^^^^^^^^^^^^^^^ +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +1. Correction + + - **Community Impact:** Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + - **Consequence:** A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why thebehavior was inappropriate. A public apology may be requested. + +2. Warning + + - **Community Impact:** A violation through a single incident or series of actions. + - **Consequence:** A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +3. Temporary Ban + + - **Community Impact:** A serious violation of community standards, including sustained inappropriate behavior. + - **Consequence:** A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +4. Permanent Ban + + - **Community Impact:** Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + - **Consequence:** A permanent ban from any sort of public interaction within the community. + +Attribution +----------- +This Code of Conduct is a modified copy of the one used by `Cantera`_, another +open-source Python project that caters to the scientific community. ``thevenin`` +maintainers hold the right to modify and update this document at any time as the +project evolves. Contributors are expected to understand that they will be held +to whichever Code of Conduct is most recent, even if they began contributing +while an older version was in use. + +Cantera's original Code of Conduct is adapted from the `Contributor Covenant`_, +version 2.0. The community Impact Guidelines were inspired by +`Mozilla's code of conduct enforcement`_. + +For answers to common questions about this code of conduct, see the `FAQ`_. +Translations are also available at `translations`_. + +.. _Cantera: https://github.com/Cantera/cantera/blob/main/CODE_OF_CONDUCT.md +.. _Contributor Covenant: https://www.contributor-covenant.org +.. _v2.0: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +.. _Mozilla's code of conduct enforcement: https://github.com/mozilla/diversity +.. _FAQ: https://www.contributor-covenant.org/faq +.. _translations: https://www.contributor-covenant.org/translations \ No newline at end of file diff --git a/docs/source/development/code_style_and_linting.rst b/docs/source/development/code_style_and_linting.rst new file mode 100644 index 0000000..73662b5 --- /dev/null +++ b/docs/source/development/code_style_and_linting.rst @@ -0,0 +1,57 @@ +Code Style and Linting +====================== +Maintaining a consistent code style and adhering to linting rules is crucial for ensuring code quality and readability. This page outlines the guidelines and tools used for code style and linting in our project. + +Styling Guidelines +------------------ +We adhere to `PEP8 `_ with minimal exceptions. Minor adjustments to spacing (around operators, under/over-indentation) are allowed when they improve clarity. We include a ``.flake8`` configuration file in ``.github/linters`` that specifies these exceptions. Developers should configure their IDEs with this file to ensure consistency. + +Code Formatting +--------------- +While `black `_ is a popular auto-formatting package, we do not permit it to be used for this codebase. Although it adheres to the same PEP8 standards that we follow, the ``black`` styling can be a bit more opinionated at times and does not always help improve clarity. For those still looking for auto-formatting, we permit the use of `autopep8 `_ is when paired with the ``.flake8`` configuration file found in ``.github/linters``. IDEs supporting ``autopep8`` should be configured accordingly. Developers can also run the formatter manually using:: + + nox -s linter -- format + +When used with the optional ``format`` argument, this ``nox`` command will first run the auto-formatter and then check for errors. This means that is errors persist, then ``autopep8`` was unable to address them and that they must be addressed manually. + +Enforcement +----------- +Style and linting are enforced through Continuous Integration (CI). Developers should perform local checks using:: + + nox -s linter + +For a comprehensive suite of checks, including unit tests and spelling in comments, run:: + + nox -s pre-commit + +This will ensure that all code meets the required standards before pushing changes. If you skip local checks, the CI will catch issues during the push process. Failed tests may result in a delayed reviewer assignments when you open pull requests. + +Documentation +------------- +Code should be documented using the `numpydoc `_ docstring format. All classes, methods, and functions must have clear docstrings, including hidden methods/functions. Use type hints to specify input and output types. Code should be readable with minimal comments, though particularly complex sections should include additional explanations. + +Additional Preferences +---------------------- +When it comes to string quotation, we have a few specific preferences to maintain consistency across the codebase: + +* **Single quotes:** + + Use single quotes (``'``) for string variables, dictionary keys, and other standard strings. For example: + + .. code-block:: python + + my_string = 'This is a string.' + my_dict = {'key': 'value'} + +* **Double quotes:** + + Use double quotes (``"``) for strings that are part of exception messages, print statements, or special string types such as formatted or raw strings. For example: + + .. code-block:: python + + print("This is a print statement.") + raise ValueError("This is an exception message.") + formatted_string = f"This is a formatted string: {value}" + raw_string = r"This is a raw string." + +By following these conventions, we aim to enhance readability and maintain consistency in how strings are handled throughout the codebase. diff --git a/docs/source/development/development_environments.rst b/docs/source/development/development_environments.rst new file mode 100644 index 0000000..b039526 --- /dev/null +++ b/docs/source/development/development_environments.rst @@ -0,0 +1,48 @@ +Development Environments +======================== +This guide will walk you through setting up a local development environment for contributing to ``thevenin``. It covers recommended practices, tools, and commands for developers to efficiently build, test, and contribute to the project. + +.. note:: + + We assume developers are already at least a little familiar with using git and GitHub. If this is not the case for you, there are many online tutorials to help you `learn git `_. + +1. Fork and clone the repository + Before setting up your local environment, make sure you have forked the main repository and cloned it from your own fork. This allows you to create pull requests from your fork to the main repo. + +2. Create a virtual environment + While developers can use any virtual environment manager, we recommend using ``conda`` if you are not already using a virtual environment tool. You can install `Anaconda `_ if needed to setup ``conda`` on your machine. + + Development should be done using the latest stable release of Python, so please setup your virtual environment accordingly. Continuous Integration (CI) workflows automatically test older versions. On occasion, if issues arise during tests, you may need to work with older Python versions temporarily. + +3. Install ``thevenin`` in editable mode + Once you have your virtual environment activated and the files locally available, install ``thevenin`` in editable mode, including the necessary development tools and dependencies, like so:: + + pip install -e .[dev] + + * Make sure you are in the same folder as the ``pyproject.toml`` file when you run this command. + * The ``-e`` flag ensures that any changes made locally will be immediately available without reinstalling. + * The ``[dev]`` argument installs all developer dependencies like linters, spellcheckers, and testing tools. + +4. Running tests + We recommend testing your installation before you start making changes. To run unit tests and make a coverage report, we have integrated ``nox``:: + + nox -s tests + + This will run all tests and generate coverage reports. You can see the coverage report by opening the ``index.html`` file in the ``reports/htmlcov/`` folder once the tests are finished. + +5. Linting, formatting, and spellchecking + All linting, formatting, and spellchecking tasks are automated. To run these checks locally:: + + nox -s linter [-- format] + nox -s codespell [-- write] + + The optional ``format`` and ``write`` arguments will attempt to format the code and correct misspellings, respectively. For more information on linting and code style, make sure you reference the :doc:`code_style_and_linting` section. + +6. Building documentation + We use `sphinx `_ to build documentation by scraping docstrings. Before you start modifying the code base, make sure the documentation builds locally:: + + nox -s docs + + You can see the local documentation build in your browser by opening the ``index.html`` file from the ``sphinx/build/`` folder. + +Now that you're all setup with a development version of ``thevenin`` and have tested the codebase using the ``nox`` integration, be sure to follow the :doc:`version_control` workflow as you contribute. Happy coding! diff --git a/docs/source/development/figures/github_flow.png b/docs/source/development/figures/github_flow.png new file mode 100644 index 0000000..d5dd482 Binary files /dev/null and b/docs/source/development/figures/github_flow.png differ diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst new file mode 100644 index 0000000..f8e5bd9 --- /dev/null +++ b/docs/source/development/index.rst @@ -0,0 +1,33 @@ +.. _development: + +Development +=========== + +.. toctree:: + :hidden: + :caption: Before you contribute + + project_overview.rst + code_of_conduct.rst + issues_and_features.rst + development_environments.rst + +.. toctree:: + :hidden: + :caption: Code structure + + project_layout.rst + patterns_and_conventions.rst + +.. toctree:: + :hidden: + :caption: Workflow + + version_control.rst + code_style_and_linting.rst + tests_and_coverage.rst + review_process.rst + +The ``thevenin`` project welcomes contributions from the community to enhance its functionality and performance. Whether you are fixing bugs, adding new features, or improving documentation, all contributions are valuable. Our goal is to make the development process as seamless as possible by providing clear guidelines and automating many of the common development tasks. + +To get started, developers should fork the repository, set up a local development environment, and follow the instructions for contributing code. We use modern tools and workflows to ensure code quality, including linters, automated tests, and continuous integration checks. Whether you're an experienced developer or just getting started, we encourage collaboration and innovation. Please refer to the specific development guides for detailed steps on setting up your environment, running tests, and following the proper branching strategies. diff --git a/docs/source/development/issues_and_features.rst b/docs/source/development/issues_and_features.rst new file mode 100644 index 0000000..e6cca7c --- /dev/null +++ b/docs/source/development/issues_and_features.rst @@ -0,0 +1,60 @@ +Issues and Features +=================== + +Overview +-------- +Before starting on a bug fix or developing a new feature for ``thevenin``, please follow the steps outlined below to ensure efficient collaboration and alignment with the project's goals. Whether you're reporting a bug, suggesting a feature, or volunteering to work on an issue, these guidelines will help maintain smooth development and communication. + +Steps to Report an Issue +------------------------ +1. Check for existing issues + + - Always check the `issues page `_ on GitHub before starting any new work. + - If a bug report or new feature request already exists, review the comments and status to see if someone is already working on it. + - If you are interested in working on the issue, leave a comment requesting the issue be assigned to you. Feel free to express your interest or add any additional context if you are experiencing the same bug or would benefit from the new feature. + +2. Report a new issue + + - If no issue exists for the bug or feature, open a new issue. Be detailed in your description, providing steps to reproduce the bug or a clear rationale for the feature. + - If you'd like to take on the issue yourself, indicate this in the issue and request that it be assigned to you. + - Before proceeding with any major work, wait for a maintainer's response to ensure the issue aligns with the project's scope and future plans. + +Best Practices +^^^^^^^^^^^^^^ +When filing an issue, follow these best practices to help the maintainers understand the problem or feature request efficiently: + +* For bugs: + - Use the "Bug Report" template. + - Clearly describe the problem and how to reproduce it. + - Specify the environment (operating system, Python version, etc.) where the bug occurred. + - Include a minimal reproducible example, relevant logs, error messages, etc. + +* For features: + - Use the "Feature Request" template. + - Explain the problem the feature will solve, and why it's important. + - Suggest how the feature should work and provide any references or examples if needed. + +Working on an Issue +------------------- +Once your issue is approved and assigned, follow the GitHub flow branching strategy for development: + +1. **Fork the repo:** If you haven't already, create a fork of the repository. + +2. **Create a Branch:** Start by creating a new branch from the main branch. Name your branch with a short description of the bug or feature. Consider including the issue number in the name as well. + +3. **Work in Manageable Chunks:** Ensure your pull request is manageable for reviewers. If your changes involve many files or a large number of lines, consider splitting the work into smaller, logical pull requests. This makes it easier for maintainers to review and approve your changes. + +4. **Submit a Pull Request:** Once your work is complete, submit a pull request (PR) to the main branch. Reference the corresponding issue in your PR description to keep everything linked and easily trackable. + +For a more detailed breakdown of these steps you will likely want to read through :doc:`version control `. + +The development team welcomes contributions! However, to keep the project maintainable and focused, it's important that every change or new feature starts with an issue. This allows maintainers to review, prioritize, and ensure the work aligns with the project's vision. + +Remember: + +* **Engage early:** Always seek feedback from maintainers before diving too deep into development, especially for larger changes or features. +* **Be considerate:** Ensure your changes are well-organized, documented, and easy to review. This will help expedite the review and approval process. + +Getting Help +------------ +If you're unsure whether your contribution fits within the scope of the project or if you need help getting started, feel free to ask questions by commenting on issues or reaching out to the maintainers. Collaboration is key to the success of ``thevenin``, and we're here to support you. diff --git a/docs/source/development/patterns_and_conventions.rst b/docs/source/development/patterns_and_conventions.rst new file mode 100644 index 0000000..55f0e80 --- /dev/null +++ b/docs/source/development/patterns_and_conventions.rst @@ -0,0 +1,108 @@ +Patterns and Conventions +======================== + +File Organization +----------------- +It is preferred to have more files with fewer lines of code rather than fewer, larger files. This keeps the codebase easier to navigate and review. As a rule of thumb, classes and functions that are long should be in their own file, while shorter, related items can be grouped together. However, take care to not group unrelated classes and/or functions just because they are short. It is okay for these to still be in their own files if they are unique and cannot be categorized to fit in with other classes/functions. + +To maintain ease of access for users, all user-facing functions and classes should be no more than three levels deep from the top-level of the package. This ensures that users do not need to navigate through excessive subpackages or submodules to find the tools they need. Keeping interfaces easily discoverable improves usability and reduces friction when working with the package. With this in mind, it is still okay for developers to have nested code, however, they should import user-facing functionality into the package or some subpackage that makes it more accessible. + +Naming Convention +----------------- +To ensure consistency and ease of development, the following conventions are enforced: + +1. File names: + All file names begin with a leading underscore (``_``) to prevent them from showing up in an editor's tab completion window. File names also use snake case (e.g., ``_my_class.py``) and are generally short but descriptive. Typically, the name of the file should reflect the class or function it contains. + +2. Class and function names: + Classes use ``CamelCase``, while functions and methods use ``snake_case``. Classes should generally be in their own file unless grouped logically with others. + +Import Considerations +--------------------- + +Ordering +^^^^^^^^ +In our codebase, import statements are organized into three distinct groups based on where the modules originate. This helps keep imports clean and maintainable. The groups, in order, are: + +1. **Standard Library Imports:** These come from Python's built-in standard library. +2. **Dependency Imports:** Imports from external dependencies installed via package managers (e.g., ``pip`` or ``conda``). +3. **Local Package Imports:** Imports that come from within our package. + +Within each group, we generally list imports in ascending order of their length (shortest to longest), as shown in the example below. This helps maintain a neat and consistent style throughout the code. Note that it is not necessary to comment each grouped section, this is only done for clarity in the example. + +.. code-block:: python + + # Standard Library Imports + import os + import sys + import datetime + + # Dependency Imports + import numpy as np + import matplotlib.pyplot as plt + + # Local Package Imports + from ._experiment import Experiment + from thevenin.plotutils import StepFunction + +Placement +^^^^^^^^^ +* Common dependencies that are used across multiple functions should be imported at the top of the module. +* For heavier dependencies or rarely used ones, consider importing them only where needed (within functions/methods) to minimize unnecessary load times. +* Regardless of placement, at the top of a file of within a function/method, ordering within each group should follow the ordering listed above. + +Class Considerations +-------------------- +For class definitions, we follow a specific ordering convention to make it easier to navigate through the code: + +1. **Magic Methods:** These special methods (e.g., ``__init__``, ``__repr__``, etc.) come first. They define key behaviors of the class. +2. **User-Facing Methods:** These are the public methods intended for external use. They define the class's core functionality for users. +3. **Hidden Methods:** These are internal methods (denoted with a leading underscore) that handle functionality not meant to be directly accessed by users. + +In some cases, exceptions to this order may be made, particularly if moving a hidden method closer to a user-facing method improves readability. However, this should be done with discretion and only when it helps clarify the flow of the class's logic. See below for an example. + +.. code-block:: python + + class MyClass: + # Magic Methods + def __init__(self, value): + self.value = value + + def __repr__(self): + return f"MyClass(value={self.value})" + + # User-Facing Methods + def do_something(self): + self._helper_function() + return f"Value is {self.value}" + + # Hidden Methods + def _helper_function(self): + # Some internal logic + pass + +Module Considerations +--------------------- +In our modules, we maintain a consistent structure to enhance readability and organization. The general order is as follows: + +1. **Classes:** If a module contains any class definitions, they should appear first. Classes define the core structure and behavior of the module. +2. **Functions:** Public functions follow the class definitions. These functions are the primary operations or utilities that the module offers for external use. +3. **Hidden Functions:** Internal functions (those with a leading underscore) come last. These are used for supporting internal logic and are not intended to be accessed directly by users. + +This ordering helps ensure that users interacting with the module can quickly identify the main components, while hidden/internal logic remains at the bottom for a clearer separation of concerns. + +Development Tools +----------------- +For ease of development, tools and dependencies for linting, formatting, spellchecking, testing, and documentation building are included as optional dependencies. Installing these is as simple as running the following:: + + pip install -e .[dev] + +In addition, developers should use ``nox`` to automate many tasks: + +* ``nox -s tests`` - run tests with coverage reports +* ``nox -s linter`` - lint and format the code +* ``nox -s codespell`` - check for and fix misspellings +* ``nox -s pre-commit`` - run pre-commit checks (all above) +* ``nox -s docs`` - build the documentation + +Use these tools to ensure the code remains clean and follows best practices. diff --git a/docs/source/development/project_layout.rst b/docs/source/development/project_layout.rst new file mode 100644 index 0000000..aa5d929 --- /dev/null +++ b/docs/source/development/project_layout.rst @@ -0,0 +1,35 @@ +Project Layout +============== +The ``thevenin`` project is organized to provide clarity and structure, making it easy for developers to navigate and contribute. Below is an outline of the key directories and files, along with guidelines for working within them. + +Root Directory +-------------- +The root directory contains the most important files and folders necessary for development: + +* **src/:** The core package code resides in this directory. This is the primary folder developers will interact with when modifying or adding features. +* **pyproject.toml:** This file contains the project's build system configurations and dependencies. If you need to add or modify dependencies, you should do so in this file. +* **noxfile.py:** Contains automation scripts for tasks like testing, linting, formatting, and building documentation. Developers should use nox sessions as needed to ensure code quality and consistency. +* **tests/:** This is where all unit tests and integration tests are stored. Any new functionality should include appropriate tests here. +* **docs/:** Contains documentation files for the project. Developers contributing to the documentation should work here, particularly if adding or improving developer guides or API references. + +Source Directory +---------------- +The ``src/`` directory contains the main package code. Using this structure ensures that local imports during development come from the installed package rather than accidental imports from the source files themselves. + +Top-level Package +^^^^^^^^^^^^^^^^^ +The core classes of the ``thevenin`` package reside at the top level of the src/ directory and include: + +* ``IDASolver``: Handles solving the differential algebraic equations used in circuit models. +* ``Model``: Represents the equivalent circuit model itself, allowing for flexible setup of different configurations. +* ``Experiment``: Manages experiments, including dynamic or static load profiles. +* ``StepSolution`` and ``CycleSolution``: Provide a structured way to return and analyze the results of simulations. + +Each of these classes typically resides in its own file, following a philosophy of keeping files manageable in size. If multiple classes or functions share significant overlap in purpose, they may be grouped in the same file, but care is taken to keep files concise and easy to navigate. + +Subpackages +^^^^^^^^^^^ +There are two subpackages that handle specific functionality: + +* ``plotutils/``: Contains utilities for visualizing simulation results. Any helper functions for plotting or figure generation live here to keep the core logic separate from visualization tasks. +* ``loadfns/``: Contains functions to assist users in building dynamic load profiles. These functions are especially useful for users looking to simulate different load scenarios in their models. diff --git a/docs/source/development/project_overview.rst b/docs/source/development/project_overview.rst new file mode 100644 index 0000000..e2737b7 --- /dev/null +++ b/docs/source/development/project_overview.rst @@ -0,0 +1,54 @@ +Project Overview +================ + +Introduction +------------ +``thevenin`` is a Python package designed to offer a simple, robust, and flexible interface for running Thevenin equivalent circuit models. Its primary focus is on simulating battery performance under various load conditions, making it an invaluable tool for researchers and scientists working on battery technologies. Whether you need to generate synthetic data, optimize parameters for real-world systems, or integrate fast, accurate models into control algorithms, ``thevenin`` is built to handle it all. + +The package provides a balance between simplicity and capability, supporting both constant and dynamic loads, and is scalable enough to fit into real-time systems. + +Key Features +^^^^^^^^^^^^ +* **Flexible Circuit Elements:** All circuit elements, including resistors and capacitors, can either be constant or depend on state of charge (SOC) and temperature. +* **Customizable RC Pairs:** The model supports any number of RC (resistor-capacitor) pairs, from zero to :math:`N`, allowing the model to scale from simple to more complex systems. +* **Thermal Modeling:** The package can operate in isothermal conditions or simulate thermal effects using a lumped thermal model for greater accuracy. +* **Versatile Experiment Interface:** The API allows for intuitive and flexible simulation of any type of load, including constant and dynamic loads driven by current, voltage, and/or power. +* **Cross-platform Support:** Written in Python, the package runs on any platform that supports Python and is continuously tested across multiple Python versions. + +Use Cases +--------- +``thevenin`` is designed for a variety of applications in the battery research space: + +* **Parameter Optimization:** The packaged models can integrate with optimization routines, enabling fast model calibration to real-world battery systems. +* **Synthetic Data Generation:** Researchers can generate synthetic data for analysis, algorithm development, or system testing. +* **Battery Model Integration:** ``thevenin`` is designed for integration with control systems, such as those using Kalman filter algorithms for real-time state estimation and battery management. + +Target Audience +--------------- +``thevenin`` is built for scientists and researchers in the battery industry. Its primary applications focus on: + +* Battery performance simulation +* State of health (SOH) estimation +* Real-time control integration + +Users who require accurate, fast models that can be integrated into control algorithms and optimization frameworks will find ``thevenin`` especially valuable. + +Technology Stack +---------------- +* **Language:** Python +* **Compatibility:** Runs on any hardware that supports Python. Multiple versions are supported. + +Project Origins +--------------- +``thevenin`` was developed by researchers at the **National Renewable Energy Laboratory (NREL)** as part of the **Rapid Operational Validation Initiative (ROVI)**, a project funded by the **Office of Electricity**. The ROVI project aims to streamline the process of validating new battery technologies and chemistries as they enter the market. ``thevenin`` contributes to this effort by providing a tool that models battery performance with flexibility and speed. If interested, you can read more about ROVI `here `_. + +Roadmap and Future Directions +----------------------------- +``thevenin`` has several exciting long-term goals: + +* **Optimization Submodule:** A future release will include an optimization submodule for automated parameter fitting to experimental data. +* **Integration with Kalman filters:** The package is currently being exercised with `moirae `_, a separate package containing Kalman filter algorithms. This will demonstrate how ``thevenin`` can be used for online state estimation, improving real-time battery management. + +Contributions +------------- +The ``thevenin`` project is hosted and actively maintained on `GitHub `_. Developers interested in contributing are encouraged to review the Code structure and Workflow sections for detailed information on the branching strategy, code review process, and how to get involved. All contributions are welcome. diff --git a/docs/source/development/review_process.rst b/docs/source/development/review_process.rst new file mode 100644 index 0000000..bf45034 --- /dev/null +++ b/docs/source/development/review_process.rst @@ -0,0 +1,46 @@ +Review Process +============== +The code review process is essential for maintaining the quality, performance, and style consistency of the project. This guide outlines the steps for submitting and reviewing pull requests (PRs), along with best practices for both contributors and reviewers. + +Reviewer Assignment +------------------- +Pull requests are reviewed by maintainers from the core development team. After submitting a PR: + +* **Assignment timing:** A reviewer should be assigned within 5 business days. If not, contributors are encouraged to leave a comment on the PR to prompt assignment. +* **CI pre-checks:** Reviewers will not be assigned until the PR passes all continuous integration (CI) tests. If your PR is failing a specific unit test and you need assistance, leave a comment on the PR so the core development team can help. + +Pull Request Requirements +------------------------- +Contributors must ensure the following before requesting a review: + +* **Pull request template:** Fill out the PR template, verifying that all criteria (e.g., style, documentation, testing) are met. +* **CI tests:** Pushes and PRs are automatically tested using CI pipelines. Ensure all tests pass before requesting a review. If certain tests are failing but the code is ready for review, mention this in the PR comments. + +Priorities and Review Criteria +------------------------------ +During the review process, the following aspects are considered: + +* **Bug fixes over features:** Bug fixes take precedence over new features in the review process. +* **Performance and clarity:** We balance the importance of code performance with clarity and readability. Clear, maintainable code is prioritized alongside well-performing implementations. +* **Best Practices:** Ensure that your PR follows the project's code style and conventions (as outlined in the :doc:`patterns_and_conventions` and :doc:`code_style_and_linting` pages). + +Timeline and Feedback +--------------------- +* **Review timeline:** Once a reviewer is assigned, contributors should expect communication at least every 48 business hours. +* **Splitting PRs:** For large or complex PRs, reviewers may request that the changes be split into smaller, more manageable PRs. +* **Reviewer feedback:** Reviewers should provide specific, actionable feedback on the code. Even when no changes are needed, the reviewer will leave a comment confirming that the PR meets all criteria. + +Addressing Feedback +------------------- +After receiving feedback: + +* **Commit changes:** Continue making commits to your branch to address reviewer comments. These updates will automatically reflect in the PR. +* **Summary and re-request:** Once all feedback is addressed, comment on the PR with a brief summary of the changes, prompting the reviewer to take another look. + +Final Approval +-------------- +Once the review process is complete: + +* **Approval:** The reviewer will approve the PR once it meets all requirements. +* **Merging:** Approved PRs are merged into the main repository. +* **Cleanup:** Developers should delete the branch once it has been merged and shift focus to the next task. diff --git a/docs/source/development/tests_and_coverage.rst b/docs/source/development/tests_and_coverage.rst new file mode 100644 index 0000000..d35bf95 --- /dev/null +++ b/docs/source/development/tests_and_coverage.rst @@ -0,0 +1,64 @@ +Tests and Coverage +================== + +Overview +-------- +Testing and coverage are critical to maintaining code quality and ensuring that our software behaves as expected. This page outlines our practices for writing and running tests, measuring coverage, and maintaining high standards in our codebase. + +Testing Practices +----------------- + +* Test organization + Tests should be organized first by module and then by class and/or function. This helps in managing and locating tests effectively. Avoid grouping tests into a single file just because they share similar functions. Instead, organize them based on their associated modules. + +* Naming conventions + All test functions should start with ``test_`` followed by a descriptive name (using snake case) indicating what is being tested. For example, ``test_calculate_total_price`` is preferable to ``test_Calculator`` unless the class is simple enough to be covered with a single test. Design tests to cover specific units, features, or applications of the class or function. + +* Test data + Use fixtures where appropriate. If mock data is necessary, make a subfolder in the ``tests/`` to store it in. Make sure the file(s) have descriptive names. Ensure that test data is manageable and not overly complex. + +Running Tests +------------- +The full test suite can be run locally using:: + + nox -s tests + +Alternatively, you can run tests from a specific file using:: + + pytest tests/test_file.py + +where ``test_file.py`` is the file that includes the tests you'd like to run. Generally, you will want to run individual files when you are iterating back and forth between fixing bugs, adding features, and writing new tests. However, you should always run the full test suite once you are finished and prior to any commits and/or pushes to your repository. + +If you forget to run tests locally they will still be run as part of the continuous integration (CI) workflow on your next push or pull request. While we only expect you to run your tests locally using the most recent stable version of Python, the CI workflow will also run the full test suite using older versions of Python and will check that tests pass on all major operating systems. + +Failing Tests +^^^^^^^^^^^^^ +It is possible that although your local tests work that one of the older versions of Python, or even the newest version of Python on a different machine, may fail. In these cases, you should check the GitHub actions logs and address the issue. Ask for help from other developers using the `Discussions `_ page if you ever feel stuck. + +A good place to start if your tests are only failing on older Python versions is to setup a second, temporarily, development environment with one of the older Python versions. All ``nox`` commands will still function the same way. This can help you run the failing tests locally instead of continuously pushing to GitHub. After failed tests are resolved, make sure you move back to using your primary development environment for future work. + +Coverage +-------- +We use ``pytest`` along with the ``pytest-cov`` extension to measure code coverage. The configuration and reports are automatically set and generated for you when you use:: + + nox -s tests + +After tests finish running, you can check the coverage by opening the ``index.html`` file in the ``reports/htmlcov/`` folder. This will help you navigate through the source code files to see which lines are and are not coveraged. + +Excluding Lines +^^^^^^^^^^^^^^^ +In some cases there will be lines of code that do not need to be covered. For example, the ``if TYPE_CHECKING`` line of code does not get run during testing and will therefore never be "covered". In this case and a few others, it is okay to use the directive ``# pragma: no cover`` to ignore a line (or section) or code. For example + +.. code-block:: python + + from tying import TYPE_CHECKING + + if TYPE_CHECKING: # pragma: no cover + from numpy import ndarray + from pandas import DataFrame + +We strive to achieve 100% test coverage (excluding lines marked by ``# pragma: no cover``); however, do not use this to avoid writing tests for challenging code. Comprehensive testing is essential for maintaining project success. + +Performance Testing +------------------- +Tests should prioritize functionality. We do not write performance tests into the test suite. If you are optimizing performance, include examples in your pull request to compare the current and new implementations. Once confirmed, these performance tests can be removed. diff --git a/docs/source/development/version_control.rst b/docs/source/development/version_control.rst new file mode 100644 index 0000000..f68b503 --- /dev/null +++ b/docs/source/development/version_control.rst @@ -0,0 +1,159 @@ +Version Control +=============== +Version control is essential to managing the development process, allowing multiple developers to work on code simultaneously, track changes, and maintain a history of the project. It enables collaboration, safeguards against errors, and helps manage releases and bug fixes effectively. + +This project follows the GitHub Flow branching strategy. This lightweight workflow is both simple and fast. Below, we will explain the key steps for contributing to this project using GitHub Flow, as well as references to other branching strategies, their pros, and cons. You'll also find instructions for handling longer feature development, merge conflicts, and patches to maintenance branches. + +.. note:: + + We assume developers are already at least a little familiar with using git and GitHub. If this is not the case for you, there are many online tutorials to help you `learn git `_. + +Branching Strategies +-------------------- +Several branching strategies are used in software development, each with its pros and cons. Below are a few common ones: + +* **Git Flow:** Git Flow is a comprehensive branching strategy with separate branches for features, releases, hotfixes, and development. It's well-suited for larger projects with multiple releases but can be overly complex for smaller teams. + + - Pros: Clear separation between development, releases, and hotfixes. + - Cons: Complicated branching structure, especially for smaller projects. + +* **Trunk-Based Development:** This approach involves a single main branch with frequent small merges directly to it. Developers create short-lived feature branches and merge back quickly. + + - Pros: Simplifies version control, encourages continuous integration. + - Cons: Requires careful management to avoid breaking changes on main. + +* **GitHub Flow:** A simpler model, ideal for projects using continuous delivery. Development happens in short-lived feature or bug branches that are merged back into ``main`` via pull requests. + + - Pros: Simple, easy to use, integrates well with CI/CD. + - Cons: Lacks formal support for maintaining multiple concurrent releases. + +For this project, we use GitHub Flow, which is explained in detail below. Interested parties can read more about any of these branching strategies `here `_. + +Project Workflow +----------------- +The ``thevenin`` project uses GitHub Flow as its version control model due to its simplicity and proven success in other scientific packages like `SciPy `_ and `Cantera `_. The workflow emphasizes short-lived feature branches, as shown in the figure below, that each address a single bug fix or feature addition. + +.. figure:: figures/github_flow.png + :align: center + :alt: Two-RC-pair Thevenin circuit. + :width: 75% + +Key Features +^^^^^^^^^^^^ +1. Main Branch: + ``main`` is the default branch that contains the latest stable developer code. It reflects the current state of development and should always be functional. + +2. Release Branches: + Each release has its own maintenance branch, e.g., ``v1.1.x``. These branches should only receive bug fixes and are not meant for new feature development. + +3. Feature and Bugfix Branches: + New features or bug fixes should be developed on separate branches off main. The naming conventions are: + + Feature branches: ``description-issue#`` + Bugfix branches: ``bug-description-issue#`` + +Note that only bug fixes should have a prefix, but all branches should reference an issue number. Use underscores between works as needed and try to keep to shorter names. The issue can always be referenced in cases where more information is needed. + +The main repository only hosts the main and release branches. Users should fork the main repo and clone the fork to get a local copy:: + + git clone https://github.com//thevenin.git + +You will likely also want to setup a remote to the upstream repository for dealing with merge conflicts and version patches, as discussed below. To set up an ``upstream`` remote use:: + + git remote add upstream https://github.com/NREL/thevenin.git + +Bug Fixes +^^^^^^^^^ +Always prioritize fixing bugs in the ``main`` branch first. Older releases should only be patched on a case-by-case basis, primarily focusing on the most recent releases. It is possible that known bugs will not be patched for versions that are more than three releases old. If you are patching ``main``, follow the directions in the :ref:`New features` section. Otherwise, to patch a bug on a previous release, follow these steps: + +1. Fetch the release branches and create a new branch off the release:: + + git fetch upstream + git checkout -b bug-description-#123 upstream/v1.1.x + +2. Work on your local branch to fix the bug. Commit and push back to your fork as needed:: + + git add . + git commit -m "Resolved bug causing ... (#123)" + git push origin bug-descriptio-#123 + +3. Submit a pull request (PR) targeting the specific release branch (e.g., ``v1.1.x``). Only bug fixes should be submitted to release branches -- no new features. Make sure you fill out the pull request template and include more detail than was provided in your commit messages. After all continuous integration (CI) checks are passing, a reviewer will be assigned and will follow up according to the :doc:`review process `. + +4. If you opened a PR and any CI checks are failing, simply continue working on your branch and committing. All extra commits will automatically be added to the PR. + +6. Repeat this processes as necessary to patch additional older versions. Unfortunately, each version needs to be patched individually, which creates more work for developers, and is the reason we prioritize which versions get patched and which do not. At a minimum, patches should always be applied to all versions between the original patched release and main. For example, patches to ``v1.1.x`` should also be applied for ``v1.2.x`` and above, including ``main``, but do not necessarily need to be submitted for ``v1.0.x``. + +.. _New features: + +New Features +^^^^^^^^^^^^ +New features should be added to branches off ``main``. Before you branch off your local branch, make sure it is up-to-date with the upstream repo. You can either use the GitHub web interface to sync your fork with the upstream repository and then run:: + + git checkout main + git pull + +or, if you setup the ``upstream`` remote, you can do this all in the command line using:: + + git fetch upstream + git checkout main + git merge upstream/main + git push origin main + +You should never commit directly to a ``main`` branch, even including your local or forked ``main`` branch. Instead, your ``main`` branch should always either be synced with the upstream repo, or should simply be behind by some number of commits depending on the last time it was synced. After syncing, create a new branch. Your new branch should be named according to the directions above depending on whether it is a bug fix or for a new feature. Here we demonstrate a new feature:: + + git checkout -b branch-name-#456 + +Once the new branch is created, follow the steps below to add your new feature: + +1. Work on your local branch to add the feature. Commit and push back to your fork as needed:: + + git add . + git commit -m "Working new feature (#456)" + git push origin branch-name-#456 + +2. Submit a pull request targeting the upstream ``main`` branch. Make sure you fill out the pull request template and include more detail than was provided in your commit messages. After all CI checks are passing, a reviewer will be assigned and will follow up according to the :doc:`review process `. + +3. If you opened a PR and any CI checks are failing, simply continue working on your branch and committing. All extra commits will automatically be added to the PR. + +4. After the PR is accepted and merged into the upstream repository, delete your new branch locally and in your GitHub repo:: + + git checkout main + git branch -d branch-name-#456 + git push origin --delete branch-name-#456 + git fetch --prune + +Merge Conflicts +--------------- +If you've submitted a PR and are seeing merge conflicts you should take the following steps: + +1. Make sure your ``main`` branch is synced with the ``upstream`` remote:: + + git fetch upstream + git checkout main + git merge upstream/main + git push main + +2. Rebase your local bug/feature branch onto ``main``:: + + git checkout branch-name-#456 + git rebase main + +3. Address merge conflicts as needed and continue the rebase:: + + git rebase --continue + +4. Recommit and push as normal and verify the merge conflict in the PR gets removed. At this point, if you are still having issues, please leave a comment in the PR asking a core developer to help out. + +Continuous Integration +---------------------- +Every pull request is automatically tested using GitHub Actions. The CI workflow runs linting, spellchecking, and tests against all major operating systems and supported Python versions. Pull requests should only be merged when all tests pass unless a core developer explicitly makes an exception (e.g., for a soon-to-be-unsupported Python version). + +Running tests locally is encouraged during development:: + + nox -s tests + +Prior to commits and pushes, we also include a ``pre-commit`` session using ``nox`` that will run through these same tests AND will check for linting and misspellings. Use this prior to pushes and/or pull requests:: + + nox -s pre-commit + +This ensures all tests pass before pushing any changes. \ No newline at end of file diff --git a/docs/source/examples/dict_inputs.ipynb b/docs/source/examples/dict_inputs.ipynb new file mode 100644 index 0000000..f892272 --- /dev/null +++ b/docs/source/examples/dict_inputs.ipynb @@ -0,0 +1,235 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Dictionary Inputs\n", + "In the previous example, the model parameters were built from a '.yaml' file. In some cases, the functional parameters are relatively complex and can be challenging to specify in the '.yaml' format. Therefore, the model can also be constructed using a dictionary, as demonstrated below.\n", + "\n", + "## Import Modules" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import thevenin as thev" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define the Parameters\n", + "In addition to the open circuit voltage (`ocv`), all circuit elements (i.e., `R0`, `R1`, `C1`, etc.) must be specified as functions. While `OCV` is only a function of the state of charge (`soc`, -), the circuit elements are function of both soc and temperature (`T_cell`, K). It is important that these are the only inputs to the functions and that the inputs are given in the correct order. \n", + "\n", + "The functions below come from fitting the equivalent circuit model to a 75 Ah graphite-NMC battery made by Kokam. Fits were performed using charge and discharge pulses from HPPC tests done at multiple temperatures. The `soc` was assumed constant during a single pulse and each resistor and capacitor element was fit as a constant for a given soc/temperature condition. Expressions below come from AI-Batt, which is an open-source software capable of semi-autonomously identifying algebraic expressions that map inputs (`soc` and `T_cell`) to outputs (`R0`, `R1`, `C1`)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "stressors = {'q_dis': 1.}\n", + "\n", + "\n", + "def calc_xa(soc: float) -> float:\n", + " return 8.5e-3 + soc*(7.8e-1 - 8.5e-3)\n", + "\n", + "\n", + "def calc_Ua(soc: float) -> float:\n", + " xa = calc_xa(soc)\n", + " Ua = 0.6379 + 0.5416*np.exp(-305.5309*xa) \\\n", + " + 0.0440*np.tanh(-1.*(xa-0.1958) / 0.1088) \\\n", + " - 0.1978*np.tanh((xa-1.0571) / 0.0854) \\\n", + " - 0.6875*np.tanh((xa+0.0117) / 0.0529) \\\n", + " - 0.0175*np.tanh((xa-0.5692) / 0.0875)\n", + "\n", + " return Ua\n", + "\n", + "\n", + "def normalize_inputs(soc: float, T_cell: float) -> dict:\n", + " inputs = {\n", + " 'T_norm': T_cell / (273.15 + 35.),\n", + " 'Ua_norm': calc_Ua(soc) / 0.123,\n", + " }\n", + " return inputs\n", + "\n", + "\n", + "def ocv_func(soc: float) -> float:\n", + " coeffs = np.array([\n", + " 1846.82880284425, -9142.89133579961, 19274.3547435787, -22550.631463739,\n", + " 15988.8818738468, -7038.74760241881, 1895.2432152617, -296.104300038221,\n", + " 24.6343726509044, 2.63809042502323,\n", + " ])\n", + " return np.polyval(coeffs, soc)\n", + "\n", + "\n", + "def R0_func(soc: float, T_cell: float) -> float:\n", + " inputs = normalize_inputs(soc, T_cell)\n", + " T_norm = inputs['T_norm']\n", + " Ua_norm = inputs['Ua_norm']\n", + "\n", + " b = np.array([4.07e12, 23.2, -16., -47.5, 2.62])\n", + "\n", + " R0 = b[0] * np.exp( b[1] / T_norm**4 * Ua_norm**(1/4) ) \\\n", + " * np.exp( b[2] / T_norm**4 * Ua_norm**(1/3) ) \\\n", + " * np.exp( b[3] / T_norm**0.5 ) \\\n", + " * np.exp( b[4] / stressors['q_dis'] )\n", + "\n", + " return R0\n", + "\n", + "\n", + "def R1_func(soc: float, T_cell: float) -> float:\n", + " inputs = normalize_inputs(soc, T_cell)\n", + " T_norm = inputs['T_norm']\n", + " Ua_norm = inputs['Ua_norm']\n", + "\n", + " b = np.array([2.84e-5, -12.5, 11.6, 1.96, -1.67])\n", + "\n", + " R1 = b[0] * np.exp( b[1] / T_norm**3 * Ua_norm**(1/4) ) \\\n", + " * np.exp( b[2] / T_norm**4 * Ua_norm**(1/4) ) \\\n", + " * np.exp( b[3] / stressors['q_dis'] ) \\\n", + " * np.exp( b[4] * soc**4 )\n", + "\n", + " return R1\n", + "\n", + "\n", + "def C1_func(soc: float, T_cell: float) -> float:\n", + " inputs = normalize_inputs(soc, T_cell)\n", + " T_norm = inputs['T_norm']\n", + " Ua_norm = inputs['Ua_norm']\n", + "\n", + " b = np.array([19., -3.11, -27., 36.2, -0.256])\n", + "\n", + " C1 = b[0] * np.exp( b[1] * soc**4 ) \\\n", + " * np.exp( b[2] / T_norm**4 * Ua_norm**(1/2) ) \\\n", + " * np.exp( b[3] / T_norm**3 * Ua_norm**(1/3) ) \\\n", + " * np.exp( b[4] / stressors['q_dis']**3 )\n", + "\n", + " return C1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Construct a Model\n", + "The model is constructed below using all necessary keyword arguments. You can see a list of these parameters using ``help(thev.Model)``." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "params = {\n", + " 'num_RC_pairs': 1,\n", + " 'soc0': 1.,\n", + " 'capacity': 75.,\n", + " 'mass': 1.9,\n", + " 'isothermal': False,\n", + " 'Cp': 745.,\n", + " 'T_inf': 300.,\n", + " 'h_therm': 12.,\n", + " 'A_therm': 1.,\n", + " 'ocv': ocv_func,\n", + " 'R0': R0_func,\n", + " 'R1': R1_func,\n", + " 'C1': C1_func,\n", + "}\n", + "\n", + "model = thev.Model(params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build an Experiment\n", + "Experiments are built using the `Experiment` class. An experiment starts out empty and is then constructed by adding a series of current-, voltage-, or power-controlled steps. Each step requires knowing the control mode/units, the control value, a relative time span, and limiting criteria (optional). Control values can be specified as either constants or dynamic profiles with sinatures like `f(t: float) -> float` where `t` is the relative time of the new step, in seconds. The experiment below discharges at a nominal C/5 rate for up to 5 hours. A limit is set such that if the voltage hits 3 V then the next step is triggered early. Afterward, the battery rests for 10 min before charging at C/5 for 5 hours or until 4.2 V is reached. The final step is a 1 hour voltage hold at 4.2 V.\n", + "\n", + "Note that the time span for each step is constructed as `(t_max: float, dt: float)` which is used to determine the time array as `tspan = np.arange(0., t_max + dt, dt)`. You can also construct a time array given `(t_max: float, Nt: int)` by using an integer instead of a float in the second position. In this case, `tspan = np.linspace(0., t_max, Nt)`. To learn more about building an experiment, including which limits are allowed and/or how to adjust solver settings on a per-step basis, see the documentation `help(thev.Experiment)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 15., (5.*3600., 60.), limits=('voltage_V', 3.))\n", + "expr.add_step('current_A', 0., (600., 5.))\n", + "expr.add_step('current_A', -15., (5.*3600., 60.), limits=('voltage_V', 4.2))\n", + "expr.add_step('voltage_V', 4.2, (3600., 60.))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run the Experiment\n", + "Experiments are run using either the `run` method, as shown below, or the `run_step` method. The difference between the two is that the `run` method will run all experiment steps with one call. If you would prefer to run the discharge first, perform an analysis, and then run the rest, etc. then you will want to use the `run_step` method. In this case, you should always start with step 0 and then run the following steps in order. When you use `run_step` the models internal state is saved at the end of each step. Therefore, after all steps have been run, you should run the `pre` method to pre-process the model back to its original initial state. All of this is handled automatically in the `run` method.\n", + "\n", + "Regardless of how you run your experiment, the return value will be a solution instance. Solution instances each contain a `vars` attribute which contains a dictionary of the output variables. Keys are generally self descriptive and include units where applicable. To quickly plot any two variables against one another, use the `plot` method with the two keys of interest specified for the `x` and `y` variables of the figure. Below, time (in hours) is plotted against voltage." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "soln = model.run(expr)\n", + "soln.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst new file mode 100644 index 0000000..7070c0c --- /dev/null +++ b/docs/source/examples/index.rst @@ -0,0 +1,37 @@ +.. _examples: + +Examples +======== +Examples below demonstrate how to set up and simulate Thevenin equivalent circuits with different configurations and experiments. These examples highlight the flexibility and ease of use of the package. Each example includes both descriptions and code snippets to help you get started with implementing your own models efficiently. + +.. grid:: 1 2 2 2 + + .. grid-item-card:: Basic tutorial + :class-footer: border-0 + :padding: 2 + + Get started by learning how to configure + model inputs and options. + + .. toctree:: + :numbered: + :titlesonly: + :caption: Basic tutorial + + yaml_inputs.ipynb + dict_inputs.ipynb + + .. grid-item-card:: Dynamic loads + :class-footer: border-0 + :padding: 2 + + Learn more about complex experiments and + debugging when steps fail. + + .. toctree:: + :numbered: + :titlesonly: + :caption: Dynamic loads + + ramping.ipynb + step_functions.ipynb diff --git a/docs/source/examples/ramping.ipynb b/docs/source/examples/ramping.ipynb new file mode 100644 index 0000000..759e60c --- /dev/null +++ b/docs/source/examples/ramping.ipynb @@ -0,0 +1,176 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Ramping\n", + "Even with robust numerical solvers and thoughtfully chosen default tolerances, simulations may occasionally fail under certain conditions. This is often due to either inconsistent initial conditions or stiffness issues that prevent proper initialization from a rested state. While our solvers are designed to handle many scenarios effectively, the following issues may still arise:\n", + "\n", + "1. **Inconsistent initial conditions:**\n", + " \n", + " Many solvers are capable of detecting and resolving inconsistent initial conditions before taking the first step. However, this feature can be disabled, allowing bad initial conditions to be passed to the solver, and generally resulting in failures.\n", + "\n", + "2. **Stiff problems:**\n", + " \n", + " Some problems are inherently stiff and cannot be initialized effectively, even with a solver's initialization correction schemes. In such cases, the solver may have difficulty determining a stable solution.\n", + "\n", + "To address these issues, introducing a ramped load can stabilize the simulation. By default, `thevenin` models are set to always ask the solver to correct the initial condition. The starting guess that gets passed to the solver is always a rested condition. Therefore, ramped loads can gradually adjust from the initial state to the desired load, making them easier for the solver to handle. This technique helps avoid the solver crashing due to an abrupt change in load.\n", + "\n", + "In this tutorial, we will demonstrate how to use the `loadfns` module to create a ramped load profile. While we will focus one specific function, other useful helper functions are available in the `loadfns` module, and we encourage you to explore the full documentation for more information." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating Ramped Demands\n", + "`thevenin` models supports both constant and dynamic load profiles for each experimental step. For example, below we make a profile that discharges the battery at a constant current until 3.5 V and then charges the battery by ramping the voltage until 4.2 V." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import thevenin as thev\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def voltage_ramp(t: float) -> float:\n", + " return 3.5 + 5e-3*t\n", + "\n", + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75., (3600., 60.), limits=('voltage_V', 3.5))\n", + "expr.add_step('voltage_V', voltage_ramp, (600., 10.), limits=('voltage_V', 4.2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This general approach provides the most flexibility so users can write any constant or dynamic load, including interpolations of data. However, we also provide select loads in the `loadfns` module that help with both solver stability and reduce the amount of code users need to write out for simple profiles. For instance, the same experiment above can also be constructed using the `Ramp` class, as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "voltage_ramp = thev.loadfns.Ramp(5e-3, 3.5)\n", + "\n", + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75., (3600., 60.), limits=('voltage_V', 3.5))\n", + "expr.add_step('voltage_V', voltage_ramp, (600., 10.), limits=('voltage_V', 4.2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below, we demonstrate running this experimental protocol so we can see that it is doing what we expect." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = thev.Model()\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_min', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stability Ramps\n", + "Aside from a constant ramp, like `Ramp` demonstrated above, ramps are also commonly used to quickly move from a rested state to a constant load. This can help with solver stability over trying to instantaneously pull a load. To build this type of provile, use the `Ramp2Constant` class. Below, we ramp up to a 20 C discharge in one millisecond and then hold the 20 C discharge rate until 3 V." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dynamic_load = thev.loadfns.Ramp2Constant(20*75/1e-3, 20*75)\n", + "\n", + "expr = thev.Experiment()\n", + "expr.add_step('current_A', dynamic_load, (180., 0.5), limits=('voltage_V', 3.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_s', 'current_A')\n", + "soln.plot('time_s', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These types of \"stability\" ramps become more and more helpful (or needed) as loads become more demanding. They can also depend on the model's parameter set, i.e., for one set of parameters the model may start crashing at a 5 C discharge whereas another set is stable up to 50 C. \n", + "\n", + "## Comparing to Instantaneous Demands\n", + "The default model parameters, and equivalent circuit models in general, is typically fairly stable compared to other higher-fidelity models (e.g., the single particle model or pseudo-2D model). Therefore, here we can also demonstrate that when we run an instantaneous 20 C discharge profile that the results are not significantly impacted. See the figure below that compares the voltage profile above to one obtained without the ramped profile." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75*20, (180., 75), limits=('voltage_V', 3.))\n", + "\n", + "soln2 = model.run(expr)\n", + "\n", + "plt.plot(soln.vars['time_s'], soln.vars['voltage_V'], '-k')\n", + "plt.plot(soln2.vars['time_s'], soln2.vars['voltage_V'], 'ok', markerfacecolor='none')\n", + " \n", + "plt.xlabel('Time [s]');\n", + "plt.ylabel('Voltage [V]');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Due to the ramp the initial conditions are obviously a bit different. However, since the ramp occurs over just one millisecond, the profile from the ramped case (solid line) very quickly adjusts to the same voltage as the case where current is instantaneous (open markers). The solutions maintain good agreement throughout the rest of discharge." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Conclusion\n", + "In this tutorial, you’ve seen how ramped loads can stabilize simulations that struggle with abrupt load changes. By using the loadfns module, you can easily implement these profiles, ensuring smoother transitions for the solver. For more advanced load functions, check out the full documentation to optimize your simulations further." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/examples/step_functions.ipynb b/docs/source/examples/step_functions.ipynb new file mode 100644 index 0000000..c163eb0 --- /dev/null +++ b/docs/source/examples/step_functions.ipynb @@ -0,0 +1,142 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Step Functions\n", + "In many experimental setups, dynamic loads are applied to simulate realistic operating conditions. Experimental platforms often handle these dynamic loads effectively, interpolating between data points if necessary to create smooth profiles. However, while interpolation is a convenient tool, there are situations where it might not be the best approach for simulating system behavior. Therefore, we also supply helper functions to construct step-based load profiles.\n", + "\n", + "## Why not interpolate?\n", + "Interpolating data can introduce a level of artificial smoothness that doesn't always reflect the abrupt changes seen in real-world systems. For example, interpolated loads are often used to ease solver convergence, but they may not capture the behavior of systems that respond rapidly to changes. This is particularly important for systems that exhibit stepwise or discrete changes in load, where instantaneous shifts between levels are more appropriate than a continuous curve.\n", + "\n", + "While writing an interpolation function is typically straightforward—requiring little more than a call to a standard library, the complexity increases when building a function that implements stepwise behavior. A step function requires more careful attention to correctly represent when and where the system load changes instantaneously. Consequently, we provide this functionality within the `loadfns` modeule to reduce the users' burden to have to develop their own. \n", + "\n", + "## Overview\n", + "When dealing with numerical simulations, introducing ramps between load changes can significantly improve the stability of the solver, reducing the risk of failure during abrupt transitions. Sudden, instantaneous changes in load can sometimes cause solvers to struggle, especially with stiff systems, leading to crashes or errors. That’s why `thevenin` offers two classes for defining stepped load profiles: `StepFunction` and `RampedSteps`.\n", + "\n", + "The `StepFunction` class is designed for scenarios where immediate, instantaneous changes in load are appropriate, while the `RampedSteps` class helps transition between steps by applying an interpolation ramps over a specified time interval at the start of each new step. These two approaches cover a wide range of scenarios, from systems that can handle rapid shifts to those that require more stable transitions.\n", + "\n", + "Below, we will cover:\n", + "1. Building load profiles using interpolated data.\n", + "2. Setting up multi-step experiments using for loops.\n", + "3. Using the `StepFunctio` class to create instantaneous stepped loads.\n", + "4. Using the `RampedSteps` class to create stable transitions between load steps.\n", + "\n", + "## Dynamic Experiments\n", + "To create dynamic load profiles, especially for more complex experiments, there are many approaches you can take. The `Experiment` class allows users to pass in any Python `Callable` like `f(t: float) -> float` to control each step. Therefore, if you have data, you can easily interpolate the data to create a load profile, or you can automate the construction of load steps using a for loop. Below we demonstrate both approaches." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import thevenin as thev\n", + "import numpy as np\n", + "\n", + "model = thev.Model()\n", + "\n", + "# Fake hour-by-hour load data\n", + "time_s = 3600.*np.array([0., 1., 2., 3., 4., 5.])\n", + "current_A = model.capacity*np.array([0.6, 0.3, -0.5, 0.2, 0.3, -0.1])\n", + "\n", + "# Interpolating the data\n", + "interp = lambda t: np.interp(t, time_s, current_A)\n", + "\n", + "expr = thev.Experiment(max_step=60.)\n", + "expr.add_step('current_A', interp, (3600*6, 60.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_h', 'current_A')\n", + "soln.plot('time_h', 'voltage_V')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the script above, the data represents hour-by-hour constant-current loads, which might represent some stationary storage system. Since the current is constant across each hour, interpolating between points poorly approximates the actual system behavior. However, interpolation might be more relevant for other dynamic systems like electric vehicles, where data is resolved on shorter timescales, such as seconds.\n", + "\n", + "A better approach for modeling constant-step experiments, rather than using interpolation, is to manually construct the steps using a for loop. In the code block below, we demonstrate how to create a new experiment with multiple steps, where each step lasts one hour, and the current is set by the values in the `current_A` array." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Looping over constant steps\n", + "expr = thev.Experiment(max_step=60.)\n", + "for amps in current_A:\n", + " expr.add_step('current_A', amps, (3600, 60.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_h', 'current_A')\n", + "soln.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This loop-based method significantly improves the accuracy of the results in this case. You can see how different the two voltage profiles are when the load profile is applied correctly, instead of using interpolation. This loop-based approach offers the most flexibility and is recommended when users need precise control over each step. For example, using the `add_step` method allows you to add different limits to each step, which can be incorporated into the loop. This level of control is not always possible with other methods.\n", + "\n", + "## Ramped Transitions\n", + "Unlike `StepFunction`, the `RampedSteps` class introduces \"smooth\" transitions between load steps by ramping up or down over a specified time period. This method is especially useful when dealing with stiff systems, where abrupt changes might otherwise cause solver instability. Below we demonstrate this using the same hour-by-hour profile from above. We set the ramp between steps to be just one millisecond so that the transitions are still quick and approximate an instantaneous change. In this case, the added ramps improve the stability and the full simulation is run, as shown in the figure. Overall, the results are nearly identical to the loop-based approach since the ramps are set to occur over such a small time scale. In particular, the main difference is shown in the current profile, where you can briefly see the first ramp (starting from zero current at `t = 0`)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Stabilize the solver with ramped steps\n", + "demand = thev.loadfns.RampedSteps(time_s, current_A, 1e-3)\n", + "\n", + "expr = thev.Experiment(max_step=60.)\n", + "expr.add_step('current_A', demand, (3600*6, 60.))\n", + "\n", + "soln = model.run(expr)\n", + "soln.plot('time_h', 'current_A')\n", + "soln.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While the `RampedSteps` class improves solver stability, it still lacks flexibility for setting limits on each individual step. For instance, you could apply limits to stop the simulation if the voltage goes outside a specific window (e.g., [3, 4.2]), but this would simply end the entire simulation prematurely. In most cases, you wouldn’t want to stop the simulation completely but instead transition to the next step early. To achieve this behavior, you would need to use loops, or alternatively, set up multiple instances of the `RampedSteps` class if you want to transition between groups of steps based on specific limits rather than between individual steps.\n", + "\n", + "In general, if maximum flexibility is needed, more manual setup is required for multi-step experiments. However, if you can work within the limitations of `RampedSteps`, it is a powerful tool for quickly constructing step-like profiles while maintaining some degree of stability.\n", + "\n", + "## Conclusion\n", + "In this tutorial, we explored various methods for constructing dynamic load profiles using the `StepFunction` and `RampedSteps` classes. We’ve shown how both instantaneous steps and ramps between steps can be modeled and discussed the trade-offs between flexibility, stability, and ease of use. While loop-based approaches offer the greatest control, `RampedSteps` provides a simple and effective way to ensure stability in simulations, making it a valuable option for many users. Ultimately, the best method depends on the complexity of the load profile you need and the requirements of your specific experiment or model." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/examples/yaml_inputs.ipynb b/docs/source/examples/yaml_inputs.ipynb new file mode 100644 index 0000000..4ed41f2 --- /dev/null +++ b/docs/source/examples/yaml_inputs.ipynb @@ -0,0 +1,190 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# YAML File Inputs\n", + "This basic example will walk you through understanding the three main classes required to build and exercise equivalent circuit models using this package. The three classes as the `Model`, `Experiment`, and `StepSolution` or `CylceSolution` classes. Models hold parameters associated with defining the battery circuit, experiments list a series of sequential steps that define a test protocol or duty cycle, and the solution classes provide an interface to access, manipulate, and/or plot the solution.\n", + "\n", + "## Import Modules" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import thevenin as thev" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Construct a Model\n", + "The model class can be constructed using either a '.yaml' file or a dictionary that specifies all keyword arguments shown in the documentation (`help(thev.Model)`). A default '.yaml' file is read in when no input is provided. This is simply for convenience to help users get up and going as quickly as possible. However, you should learn how to write your own '.yaml' file or dictionary input if you would like to use this package to its fullest extent. \n", + "\n", + "The '.yaml' format is very similar to building a dictionary in Python. Use the default 'params.yaml' file given below as a template for your own files. Note that the open circuit voltage `ocv` and circuit elements (`R0`, `R1`, and `C1`) must be input as a `Callable` with the correct inputs in the correct order, i.e., `f(soc: float) -> float` for `ocv` and `f(soc: float, T_cell: float) -> float` for all RC elements. The inputs represent the state of charge (`soc`, -) and cell temperature (`T_cell`, K). Resistor and capacitor outputs should be in Ohm and F, respectively. Since '.yaml' files do not natively support python functions, this package uses a custom `!eval` constructor to interpret functional parameters. The `!eval` constructor should be followed by a pipe `|` so that the interpreter does not get confused by the colon in the `lambda` expression. `np` expressions and basic math are also supported when using the `!eval` constructor.\n", + "\n", + "```yaml\n", + "num_RC_pairs: 1\n", + "soc0: 1.\n", + "capacity: 75.\n", + "mass: 1.9\n", + "isothermal: False\n", + "Cp: 745.\n", + "T_inf: 300.\n", + "h_therm: 12.\n", + "A_therm: 1.\n", + "ocv: !eval | \n", + " lambda soc: 84.6*soc**7 - 348.6*soc**6 + 592.3*soc**5 - 534.3*soc**4 \\\n", + " + 275.*soc**3 - 80.3*soc**2 + 12.8*soc + 2.8\n", + "R0: !eval |\n", + " lambda soc, T_cell: 1e-4 + soc/1e5 - T_cell/3e7\n", + "R1: !eval |\n", + " lambda soc, T_cell: 1e-5 + soc/1e5 - T_cell/3e7\n", + "C1: !eval |\n", + " lambda soc, T_cell: 1e4 + soc*1e4 + np.exp(T_cell/300.)\n", + "```\n", + "\n", + "Although this example only uses a single RC pair, `num_RC_pairs` can be as low as 0 and can be as high as $N$. The number of defined `Rj` and `Cj` elements in the '.yaml' file should be consistent with `num_RC_pairs`. For example, if `num_RC_pairs=0` then only `R0` should be defined, with no other resistors or capacitors. However, if `num_RC_pairs=3` then the user should specify `R0`, `R1`, `R2`, `R3`, `C1`, `C2`, and `C3`. Note that the series resistor element `R0` is always included, even when there are no RC pairs. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = thev.Model()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When using the default parameters, a warning will always print. This is to ensure the user is running with their preferred inputs. In the case that a user has a file by the same name, the package will take the default as its preference. Be sure to specify the local or absolute path in this case, e.g., `./params.yaml`, or simply rename your file.\n", + "\n", + "## Build an Experiment\n", + "Experiments are built using the `Experiment` class. An experiment starts out empty and is then constructed by adding a series of current-, voltage-, or power-controlled steps. Each step requires knowing the control mode/units, the control value, a relative time span, and limiting criteria (optional). Control values can be specified as either constants or dynamic profiles with sinatures like `f(t: float) -> float` where `t` is the relative time of the new step, in seconds. The experiment below discharges at a nominal 1C rate for up to 1 hour. A limit is set such that if the voltage hits 3 V then the next step is triggered early. Afterward, the battery rests for 10 min before charging at 1C for 1 hours or until 4.3 V is reached. The remaining three steps perform a voltage hold at 4.3 V for 10 min, a constant power profile of 200 W for 1 hour or until 3.8 V is reached, and a sinusoidal voltage load for 10 min centered around 3.8 V.\n", + "\n", + "Note that the time span for each step is constructed as `(t_max: float, dt: float)` which is used to determine the time array as `tspan = np.arange(0., t_max + dt, dt)`. You can also construct a time array given `(t_max: float, Nt: int)` by using an integer instead of a float in the second position. In this case, `tspan = np.linspace(0., t_max, Nt)`. To learn more about building an experiment, including which limits are allowed and/or how to adjust solver settings on a per-step basis, see the documentation `help(thev.Experiment)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dynamic_load = lambda t: 10e-3*np.sin(2.*np.pi*t / 120.) + 3.8\n", + "\n", + "expr = thev.Experiment(max_step=10.)\n", + "expr.add_step('current_A', 75., (3600., 1.), limits=('voltage_V', 3.))\n", + "expr.add_step('current_A', 0., (600., 1.))\n", + "expr.add_step('current_A', -75., (3600., 1.), limits=('voltage_V', 4.3))\n", + "expr.add_step('voltage_V', 4.3, (600., 1.))\n", + "expr.add_step('power_W', 200., (3600., 1.), limits=('voltage_V', 3.8))\n", + "expr.add_step('voltage_V', dynamic_load, (600., 1.))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run the Experiment\n", + "Experiments are run using either the `run` method, as shown below, or the `run_step` method. The difference between the two is that the `run` method will run all experiment steps with one call. If you would prefer to run the discharge first, perform an analysis, and then run the rest, etc. then you will want to use the `run_step` method. In this case, you should always start with step 0 and then run the following steps in order. When you use `run_step` the models internal state is saved at the end of each step. Therefore, after all steps have been run, you should run the `pre` method to pre-process the model back to its original initial state. All of this is handled automatically in the `run` method.\n", + "\n", + "Regardless of how you run your experiment, the return value will be a solution instance. Solution instances each contain a `vars` attribute which contains a dictionary of the output variables. Keys are generally self descriptive and include units where applicable. To quickly plot any two variables against one another, use the `plot` method with the two keys of interest specified for the `x` and `y` variables of the figure. Below, time (in hours) is plotted against voltage." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sol = model.run(expr)\n", + "sol.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run step-by-step, perform the following." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run each index, starting with 0\n", + "solns = []\n", + "for i in range(expr.num_steps):\n", + " solns.append(model.run_step(expr, i))\n", + " \n", + "# Re-run the pre-processor in case you'd like to run another experiment\n", + "model.pre()\n", + " \n", + "# Look at the first step solution (i.e., the 1C discharge)\n", + "solns[0].plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you run an experiment step-by-step, you can also manually stitch them together into a `CycleSolution` once you are finished. Alternatively, if you have a `CycleSolution`, you can pull a single `StepSolution` or a subset of the `CycleSolution` using the `get_steps` method. See below for an example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Stitch the step solutions together\n", + "cycle_soln = thev.CycleSolution(*solns)\n", + "cycle_soln.plot('time_h', 'voltage_V')\n", + "\n", + "# Pull steps 1--3 (inclusive)\n", + "some_steps = cycle_soln.get_steps((1, 3))\n", + "some_steps.plot('time_h', 'voltage_V')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..203e80f --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,138 @@ +.. .. raw:: html + +.. +..
+.. logo +.. logo +..
+..
+.. + +======= +Summary +======= +The Thevenin equivalent circuit model is a common low-fidelity battery model consisting of a single resistor in series with any number of RC pairs, i.e., parallel resistor-capacitor pairs. This Python package contains an API for building and running experiments using Thevenin models. When referring to the model itself, we use capitalized "Thevenin", and for the package lowercase ``thevenin``. + +.. toctree:: + :caption: User Guide + :hidden: + :maxdepth: 2 + + User Guide + +.. toctree:: + :caption: API Reference + :hidden: + :maxdepth: 2 + + API Reference + +.. toctree:: + :caption: Examples + :hidden: + :maxdepth: 2 + + Examples + +.. toctree:: + :caption: Development + :hidden: + :maxdepth: 2 + + Development + +**Version:** |version| + +**Useful links:** +`anaconda `_ | +`spyder `_ | +`numpy `_ | +`scikit-sundae `_ | +`matplotlib `_ + +.. grid:: 1 2 2 2 + + .. grid-item-card:: User Guide + :class-footer: border-0 + :padding: 2 + + Access installation instructions and in-depth + information on solver concepts and settings. + + .. image:: _static/user_guide.svg + :class: bg-transparent + :align: center + :height: 75px + + +++ + .. button-ref:: user_guide/index + :expand: + :color: primary + :click-parent: + + To the user guide + + .. grid-item-card:: API Reference + :class-footer: border-0 + :padding: 2 + + Get detailed documentation on all of the modules, + functions, classes, etc. + + .. image:: _static/api_reference.svg + :class: bg-transparent + :align: center + :height: 75px + + +++ + .. button-ref:: api/thevenin/index + :expand: + :color: primary + :click-parent: + + Go to the docs + + .. grid-item-card:: Examples + :class-footer: border-0 + :padding: 2 + + A great place to learn how to use the package and + expand your skills. + + .. image:: _static/examples.svg + :class: bg-transparent + :align: center + :height: 75px + + +++ + .. button-ref:: examples/index + :expand: + :color: primary + :click-parent: + + See some examples + + .. grid-item-card:: Development + :class-footer: border-0 + :padding: 2 + + Trying to fix a typo in the documentation? Looking + to improve or add a new feature? + + .. image:: _static/development.svg + :class: bg-transparent + :align: center + :height: 75px + + +++ + .. button-ref:: development/index + :expand: + :color: primary + :click-parent: + + Read contributor guidelines + + + \ No newline at end of file diff --git a/docs/source/user_guide/basic_tutorial.ipynb b/docs/source/user_guide/basic_tutorial.ipynb new file mode 100644 index 0000000..fbb390e --- /dev/null +++ b/docs/source/user_guide/basic_tutorial.ipynb @@ -0,0 +1,273 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic Tutorial\n", + "The `thevenin` package is built around three main classes:\n", + "\n", + "1. `Model` - used to construct instances of an equivalent circuit.\n", + "2. `Experiment` - used to define an experimental protocol containing current, voltage, and/or power-controlled steps.\n", + "3. `Solution` - the result object(s) that contain simulation outputs when a particular model runs a particular experiment.\n", + "\n", + "Each of these classes exist at the base package level so they are easily accessible. In this tutorial you will be introduced to each of class through a minimal example. The example will demonstrate a typical workflow for constructing a model, defining an experiment, and interacting with the solution.\n", + "\n", + "## Construct a Model\n", + "The model class is constructed by providing options and parameters that define your circuit. The input can be given as either a dictionary or using a `.yaml` file. If you do not give an input, we include a default parameters file for you to get started. However, it is important that you understand this file and/or its dictionary equivalent so you can modify parameter definitions as necessary later. For more information about constructing model inputs, see the {ref}`examples ` section.\n", + "\n", + "Here, we will start by simply using the default parameters. A warning will print when the default parameters are accessed, but we can ignore it. After initialization, the class can be printed to check all of the constant options/parameters. The model also contains functional parameters, i.e., properties that change as a function of state of charge (soc) and/or temperature. These values are difficult to represent in the printed output so they are not displayed." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model(\n", + " num_RC_pairs=1,\n", + " soc0=1.0,\n", + " capacity=75.0,\n", + " mass=1.9,\n", + " isothermal=False,\n", + " Cp=745.0,\n", + " T_inf=300.0,\n", + " h_therm=12.0,\n", + " A_therm=1.0,\n", + ")\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[thevenin UserWarning] Using the default parameter file 'params.yaml'.\n", + "\n" + ] + } + ], + "source": [ + "import thevenin as thev\n", + "\n", + "model = thev.Model()\n", + "print(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Options and parameters can be changed after initialization by modifying the corresponding attribute. However, if you modify anything after initialization, you should ALWAYS run the preprocessor `pre()` method afterward. This method is run automatically when the class is first initialized, but needs to be run again manually in some cases. One such case is when options and/or parameters are changes. Forgetting to do this will cause the internal state and options to not be self consistent. We demonstrate the correct way to make changes below, by setting the `isothermal` option to `True`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "model.isothermal = True \n", + "model.pre()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define an Experiment\n", + "The model has two methods, `run()` and `run_step()` that correspond to the steps of the `Experiment` class. Similar to how a typical battery cycler would be programmed, an experiment is built by defining a series of sequential steps. Each step has its own mode (current, voltage, or power), value, time span, and limiting criteria.\n", + "\n", + "While we will not cover solver options in this tutorial, you should know that these options exist and are controlled through the `Experiment` class. Options that should be consistent throughout all steps should be set with keyword arguments when the class instance is created. You can also modify solver options at the per-step level (e.g., tighter tolerances) if needed. For more information, see the full documentation.\n", + "\n", + "Below we construct an experiment instance with two simple steps. The first step discharges the battery at a constant current until it reaches 3 V. Afterward, the battery rests for 10 minutes. Note that the sign convention for current and power are such that positive values discharge the cell and negative values charge the cell." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "expr = thev.Experiment()\n", + "expr.add_step('current_A', 75., (4000., 60.), limits=('voltage_V', 3.))\n", + "expr.add_step('current_A', 0., (600., 60.))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are also control modes available for both voltage and power, and while we do not demonstrate it here, the load value does not need to be constant. By passing in a callable like `f(t) -> float` where `t` is time and the return value is your load at that time, you can also run a dynamic profiles within a step. \n", + "\n", + "Pay attention to two important details in the example above:\n", + "\n", + "1. The `tspan` input (third argument) uses 4000 seconds in the first step even though the current is chosen such that the battery should dischange within an hour. When `limits` is used within a step, and you want to guarantee the limit is actually reached, you will want to pick a time beyond when you expect the limiting event to occur.\n", + "2. The value `60.` in the second position of the `tspan` argument contains a trailing decimal on purpose. When the decimal is present, Python interprets this as a float rather than an integer. The time step behavior is sensitive to this. When a float is passed, the solution is saved in intervals of this value (here, every 60 seconds). If an integer is passed instead, the full timespan is split into that number of times. In otherwords, `dt = tspan[0] / (tspan[1] - 1)`. We recommend always use floats for steps that have limits.\n", + "\n", + "## Run the Simulation\n", + "As mentioned above, the model contains two methods to run an experiment. You can either run the entire series of experiment steps by calling `run()`, or you can run one step at a time by calling `run_step()`. The most important difference between the two is that the model's internal state is changed and saved at the end of each step when using `run_step()` so that it is ready for the following step. Therefore, steps should only ever be run in sequential order, and steps between multiple experiments should not be mixed. For example, to run the above two steps one at a time, run the following code." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "soln_0 = model.run_step(expr, 0)\n", + "soln_1 = model.run_step(expr, 1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Indexing starts at zero to be consistent with the Python language. When steps are run one at a time, the output will be a `StepSolution`, which we discuss more below. \n", + "\n", + "It is common to setup multiple experiments that you'd like a model to run and to loop over them. For example, maybe you want to simulate different discharge rates using one experiment per rate. When using the `run()` method, you can do these back-to-back without much thought, however, when using `run_step()`, the `pre()` method should always be called before switching to another experiment. Otherwise, after the first experiment, the internal state will be at `soc = 0` and when the following experiment tries to discharge the cell at a higher rate, the results will not be physical. Likely this will lead to a crash. Therefore, before we demonstrate the `run()` method, we will call `pre()` to reset the model state from the steps run above." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "model.pre()\n", + "\n", + "soln = model.run(expr)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Interacting with Solutions\n", + "Simulation outputs will give one of two solution objects depending on your run mode. A `StepSolution` is returned when you run step by step and a `CycleSolution` is returned when using `run()`. The latter simply stitches together the individual step solutions. Each solution object has numerous attributes to inform the user whether or not their simulation was successful, how long the integrator took, etc. For `CycleSolution` instances, most of these values are lists where each index corresponds to experimental steps with the same indices. For example, below we see that both steps were successful and the total integration time." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "success = [True, True]\n", + "0.013 s\n" + ] + } + ], + "source": [ + "print(f\"success = {soln.success}\")\n", + "print(soln.solvetime)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Most likely, everything else you will need to extract from solutions can be found in the solution's `vars` dictionary. This dictionary contains easy to read names and units for all of the model's outputs. You can always check the keys to this dictionary by printing the solution instance." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CycleSolution(\n", + " solvetime=0.013 s,\n", + " success=[True, True],\n", + " status=[2, 1],\n", + " nfev=[232, 39],\n", + " njev=[34, 23],\n", + " vars=['time_s', 'time_min', 'time_h', 'soc', 'temperature_K', 'voltage_V',\n", + " 'current_A', 'power_W', 'capacity_Ah', 'eta0_V', 'eta1_V'],\n", + ")\n" + ] + } + ], + "source": [ + "print(soln)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "All values in the `vars` dictionary are 1D arrays that provide the values of the named variable at each integrator step. You can plot any two variables against each other using the `plot()` method. For example, to see voltage plotted against time, see below." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "soln.plot('time_min', 'voltage_V')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It can also be helpful to extract portions of a `CycleSolution` to examine what occurred within a given step, or to combine `StepSolution` instances so that you can post process or plotting purposes. Both of these features are available, as shown below." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "soln_0 = soln.get_steps(0)\n", + "soln_1 = soln.get_steps(1)\n", + "\n", + "soln = thev.CycleSolution(soln_0, soln_1)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "rovi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/source/user_guide/equivalent_circuit_models.rst b/docs/source/user_guide/equivalent_circuit_models.rst new file mode 100644 index 0000000..5e244bf --- /dev/null +++ b/docs/source/user_guide/equivalent_circuit_models.rst @@ -0,0 +1,47 @@ +Equivalent Circuit Models +========================= +Equivalent circuit models (ECMs) are a class of simplified mathematical models used to represent the dynamic behavior of electrochemical devices, such as batteries, supercapacitors, and fuel cells. These models approximate the system's behavior using a combination of resistors, capacitors, and sometimes inductors, rather than attempting to model the underlying physics in detail. By abstracting the system into a circuit, ECMs provide a balance between model accuracy and computational efficiency, making them an attractive choice for many real-time applications such as state estimation, control, and diagnostics. + +ECMs are versatile and have a range of applications, including: + +* **Battery Management Systems (BMS):** Thevenin and Dual Polarization models are commonly used in BMS to estimate state of charge (SOC), state of health (SOH), and to predict voltage behavior under various load conditions. +* **Real-Time Control:** Due to their computational simplicity, ECMs are used in embedded systems to control devices in real time, such as regulating voltage or current in energy storage systems. +* **Diagnostics and Prognostics:** ECMs are often used in diagnostic applications to detect faults, degradation, or abnormal behaviors in electrochemical systems. +* **Simulations and Design:** Engineers and researchers can use ECMs to simulate the behavior of batteries, fuel cells, or capacitors in a variety of operating conditions, enabling better system design and optimization. + +Types of ECMs +------------- +Several ECMs are used in the literature, each with varying complexity and accuracy. Below is a summary of some common ECM types and their typical use cases: + +1. **Rint Model:** The Resistance-Only (Rint) model is a very simple ECM that only uses a voltage source and an internal resistance. + + - Advantages: + - Extremely simple and computationally efficient. + - Only need to characterize and fit one circuit element. + - Disadvantages: + - Unable to capture relaxation effects. + - Typical Uses: + - Rough estimations of voltage drop under load, simple first-order approximations. + +2. **Randles Model:** The Randles model is another common ECM, typically used for electrochemical impedance spectroscopy (EIS) studies. It features a resistor in series with a parallel combination of a capacitor and a Warburg element (representing diffusion). + + - Advantages: + - Can represent both charge transfer and diffusion effects. + - Well-suited for impedance analysis. + - Disadvantages: + - More complex, requiring additional parameters. + - Not as computationally efficient in real-time scenarios. + - Typical Uses: + - Impedance spectroscopy analysis. + +3. **Thevenin Model:** The Thevenin model is one of the most widely used ECMs for batteries. It consists of a voltage source, an internal resistance, and one or more RC pairs. The RC pairs capture dynamic behaviors such as relaxation and charge redistribution over time. + + - Advantages: + - Simple to implement. + - Efficient for real-time applications. + - Adequately captures short-term dynamics. + - Disadvantages: + - Limited accuracy for long-term dynamics or systems with significant hysteresis. + - Can oversimplify complex electrochemical processes. + - Typical Uses: + - Real-time battery management systems, rapid simulation of transient responses. diff --git a/docs/source/user_guide/figures/2RC_circuit.png b/docs/source/user_guide/figures/2RC_circuit.png new file mode 100644 index 0000000..ba33c6d Binary files /dev/null and b/docs/source/user_guide/figures/2RC_circuit.png differ diff --git a/docs/source/user_guide/index.rst b/docs/source/user_guide/index.rst new file mode 100644 index 0000000..755998f --- /dev/null +++ b/docs/source/user_guide/index.rst @@ -0,0 +1,20 @@ +User guide +========== +Welcome to the user guide, your go-to resource for understanding and utilizing the ``thevenin`` package. Whether you're new to circuit modeling or a seasoned user looking to simulate complex battery behavior, this guide will walk you through the package's features and capabilities. You'll find a description of the model, easy-to-follow instructions for installation, explanations of the package's core concepts, and practical examples for building and using the equivalent cicuit models. + +The ``thevenin`` package is designed with simplicity in mind, providing a user-friendly interface for modeling circuits that account for both state-of-charge and temperature-dependent properties. This guide will help you understand how to simulate different types of loads, from constant current to dynamic voltage and power-driven scenarios, using the package's experiment interface. + +.. toctree:: + :hidden: + :caption: Getting started + + what_is_thevenin.rst + installation.rst + +.. toctree:: + :hidden: + :caption: Fundamentals and usage + + equivalent_circuit_models.rst + model_description.rst + basic_tutorial.ipynb diff --git a/docs/source/user_guide/installation.rst b/docs/source/user_guide/installation.rst new file mode 100644 index 0000000..6f6ac3d --- /dev/null +++ b/docs/source/user_guide/installation.rst @@ -0,0 +1,33 @@ +Installation +============ +This page will guide you through the installation process for ``thevenin``. Whether you are looking to install the package via ``pip`` from PyPI, ``conda`` from the conda-forge channel, or from the source distribution, this page has you covered. + +Installing via PyPI +------------------- +Installing with ``pip`` will pull a distribution file from the Python Package Index (PyPI). We provide both binary and source distributions on `PyPI `_. + +To install the latest release, simply run the following:: + + pip install thevenin + +Installing via conda-forge +-------------------------- +To install via ``conda``, you must specify the conda-forge channel. You can install the package with the following:: + + conda install -c conda-forge thevenin + +Be aware that our conda-forge releases are less likely to get patches than PyPI releases when it comes to older software versions. For example, if the software has moved on to v1.1, then a patch for v1.0 will likely not make its way to conda. + +Python Version Support +---------------------- +Please note that ``thevenin`` releases only support whichever Python versions are actively maintained at the time of the release. If you are using a version of Python that has reached the end of its life, as listed on the `official Python release page`_, you may need to install an older version of ``thevenin`` or upgrade your Python version. We recommend, however, upgrading your Python version instead of using an older version of ``thevenin``. + +.. _official Python release page: https://devguide.python.org/versions/ + +Developer Versions +------------------ +The development version is ONLY hosted on GitHub. To install it, see the :doc:`/development/index` section. You should only do this if you: + +* Want to try experimental features +* Need access to unreleased fixes +* Would like to contribute to the package diff --git a/docs/source/user_guide/model_description.rst b/docs/source/user_guide/model_description.rst new file mode 100644 index 0000000..03077f8 --- /dev/null +++ b/docs/source/user_guide/model_description.rst @@ -0,0 +1,46 @@ +Model Description +================= +This page outlines the underlying mathematics of the Thevenin equivalent circuit model. The index :math:`j` is used throughout the documentation to gernalize the fact that the model can be run with a variable number of resistor-capacitor (RC) elements. When zero RC pairs are specified, the model collapses into the simpler Rint model, discussed :doc:`here `. However, the model also allows any nonzero number of RC pairs, within reason. The figure below illustrates an example Thevenin circuit with two RC pairs. + +.. figure:: figures/2RC_circuit.png + :align: center + :alt: Two-RC-pair Thevenin circuit. + :width: 75% + +The Thevenin circuit is governed by the evolution of the state of charge (soc, -), RC overpotentials (:math:`V_j`, V), cell voltage (:math:`V_{\rm cell}`, V), and temperature (:math:`T_{\rm cell}`, K). soc and :math:`V_j` evolve in time as + +.. math:: + + \begin{align} + &\frac{d\rm soc}{dt} = \frac{-I}{3600 Q_{\rm max}}, \\ + &\frac{dV_j}{dt} = -\frac{V_j}{R_jC_j} + \frac{I}{C_j}, + \end{align} + +where :math:`I` is the load current (A), :math:`Q_{\rm max}` is the maximum nominal cell capacity (Ah), and :math:`R_j` and :math:`C_j` are the resistance (Ohm) and capacitance (F) of each RC pair :math:`j`. Note that the sign convention for :math:`I` is chosen such that positive :math:`I` discharges the battery (reduces soc) and negative :math:`I` charges the battery (increases soc). This convention is consistent with common physics-based models, e.g., the single particle model or pseudo-2D model. While not explicitly included in the equations above, :math:`R_j` and :math:`C_j` are functions of soc and :math:`T_{\rm cell}`. The temperature increases while the cell is active according to + +.. math:: + + \begin{equation} + mC_p\frac{dT_{\rm cell}}{dt} = \dot{Q}_{\rm gen} + \dot{Q}_{\rm conv}, + \end{equation} + +where :math:`m` is mass (kg), :math:`C_p` is specific heat capacity (J/kg/K), :math:`\dot{Q}_{\rm gen}` is the heat generation (W), and :math:`\dot{Q}_{\rm conv}` is the convective heat loss (W). Heat generation and convection are defined by + +.. math:: + + \begin{align} + &\dot{Q}_{\rm gen} = I \times (V_{\rm ocv}({\rm soc}) - V_{\rm cell}), \\ + &\dot{Q}_{\rm conv} = hA(T_{\infty} - T_{\rm cell}), + \end{align} + +where :math:`h` is the convecitive heat transfer coefficient (W/m\ :sup:`2`/K), :math:`A` is heat loss area (m\ :sup:`2`), and :math:`T_{\infty}` is the air/room temperature (K). :math:`V_{\rm ocv}` is the open circuit voltage (V) and is a function of soc. + +The overall cell voltage is + +.. math:: + + \begin{equation} + V_{\rm cell} = V_{\rm ocv}({\rm soc}) - \sum_j V_j - IR_0, + \end{equation} + +where :math:`R_0` the lone series resistance (Ohm), as shown in Figure 1. Just like the other resistive elements, :math:`R_0` is a function of soc and :math:`T_{\rm cell}`. \ No newline at end of file diff --git a/docs/source/user_guide/what_is_thevenin.rst b/docs/source/user_guide/what_is_thevenin.rst new file mode 100644 index 0000000..4639446 --- /dev/null +++ b/docs/source/user_guide/what_is_thevenin.rst @@ -0,0 +1,20 @@ +What is ``thevenin``? +===================== +``thevenin`` is a Python package designed for running equivalent circuit models, a widely used approach for modeling the electrical behavior of complex systems, such as batteries and other electrochemical devices. The package allows users to simulate circuits that consist of a voltage source, a series resistor, and some number of resistor-capacitor (RC) pairs, which represent different dynamic behaviors of the system. With ``thevenin``, users can specify the number of RC pairs to tailor the model to their needs. An example circuit is shown in the figure below with two RC elements, but the model can be set to have as few as zero and as many as :math:`N`. The package also offers the flexibility to run the model either isothermally (with constant temperature) or with temperature dependence, making it suitable for a wide range of applications. + +.. figure:: figures/2RC_circuit.png + :align: center + :alt: Two-RC-pair Thevenin circuit. + :width: 75% + +The model allows each of the circuit elements to have functional parameters, i.e., values that depend on the state of the system. Resistance and capacitance values can be expressed in terms of both state of charge and temperature. To calibrate the model to a specific system, it is common to fit each of these values to cell data at different temperatures and states of charge (SOC) and then to use those fits to find algebraic expressions that describe their dependence on SOC and temperature. Alternatively, a parameterized table can also be used for interpolation to provide circuit element parameters after fitting. While this package does not natively include a fitting strategy, the model is fast and can easily be set up with optimization routines. We recommend the `scipy.optimize `_ package for those looking to take this approach. + +Use Cases +========= +The thevenin package is particularly useful for battery modeling and simulation, where predicting voltage response to varying loads is crucial. Engineers and researchers can use it to simulate state-of-charge-dependent behavior or investigate the effects of temperature fluctuations on system performance. The package is ideal for designing and testing control algorithms, predicting system performance under dynamic loads, or conducting model-based diagnostics and state estimation in energy storage applications. + +Acknowledgements +================ +This work was authored by the National Renewable Energy Laboratory (NREL), operated by Alliance for Sustainable Energy, LLC, for the U.S. Department of Energy (DOE). The views expressed in the package and its documentation do not necessarily represent the views of the DOE or the U.S. Government. + +The motivation and funding for this project came from the Rapid Operational Validation Initiative (ROVI) sponsored by the Office of Electricity. The focus of ROVI is "to greatly reduce time required for emerging energy storage technologies to go from lab to market by developing new tools that will accelerate the testing and validation process needed to ensure commercial success." If interested, you can read more about ROVI `here `_. diff --git a/images/tests.svg b/images/tests.svg index e295e07..320f899 100644 --- a/images/tests.svg +++ b/images/tests.svg @@ -1,5 +1,5 @@ - - tests: 32 + + tests: 29 @@ -15,7 +15,7 @@ tests - - 32 + + 29 diff --git a/noxfile.py b/noxfile.py index be4ecc9..dd0c415 100644 --- a/noxfile.py +++ b/noxfile.py @@ -61,14 +61,14 @@ def run_spellcheck(session): """ - command = ['codespell'] + command = ['codespell', '--config=.github/linters/.codespellrc'] if 'write' in session.posargs: - command.append('-w') + command.insert(1, '-w') run_codespell(session) - session.run(*command, 'sphinx/source') + session.run(*command, 'docs/source') @nox.session(name='tests', python=False) @@ -132,7 +132,7 @@ def run_sphinx(session): """ if 'clean' in session.posargs: - os.chdir('sphinx') + os.chdir('docs') session.run('make', 'clean') if os.path.exists('source/api'): @@ -142,7 +142,7 @@ def run_sphinx(session): run_spellcheck(session) - session.run('sphinx-build', 'sphinx/source', 'sphinx/build') + session.run('sphinx-build', 'docs/source', 'docs/build') @nox.session(name='pre-commit', python=False) @@ -150,8 +150,8 @@ def run_pre_commit(session): """ Run all linters/tests and make new badges - Order of sessions: flake8, codespell, pytest, genbade. Using 'write' for - codespell and/or 'parallel' for pytest is permitted. + Order of sessions: flake8, codespell, pytest, genbade. Using 'format' for + linter, 'write' for codespell, and/or 'parallel' for pytest is permitted. """ diff --git a/pyproject.toml b/pyproject.toml index 180274b..4b2613e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,24 +6,35 @@ build-backend = "setuptools.build_meta" name = "thevenin" readme = "README.md" dynamic = ["version"] -description = "Packaged Thevenin equivalent circuit model." -requires-python = ">=3.9,<3.13" -authors = [{name = "Corey R. Randall", email = "corey.randall@nrel.gov"}] -maintainers = [{name = "Corey R. Randall", email = "corey.randall@nrel.gov"}] +description = "Equivalent circuit models in Python." +keywords = ["ECM", "equivalent", "circuit", "model", "battery"] +requires-python = ">=3.9,<3.14" +license = { file = "LICENSE" } +authors = [ + { name = "Corey R. Randall" }, + { email = "corey.randall@nrel.gov" }, +] +maintainers = [ + { name = "Corey R. Randall" }, + { email = "corey.randall@nrel.gov" }, +] classifiers = [ - "Development Status :: 4 - Beta", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dependencies = [ "numpy", - "scikits-odes-sundials", "scipy", "matplotlib", "ruamel.yaml", + "scikit-sundae", ] [tool.setuptools.dynamic] @@ -33,7 +44,7 @@ version = {attr = "thevenin.__version__"} where = ["src"] [tool.setuptools.package-data] -thevenin = ["templates/*.yaml",] +thevenin = ["templates/*.yaml"] [project.optional-dependencies] dev = [ @@ -42,20 +53,29 @@ dev = [ "pytest-cov", "pytest-xdist", "genbadge[all]", - "codespell", "flake8", "autopep8", + "codespell", "sphinx", - "sphinx-autoapi", + "myst-nb", "sphinx-design", + "sphinx-autoapi", "sphinx-favicon", "sphinx-copybutton", + "pydata-sphinx-theme", +] +docs = [ + "sphinx", "myst-nb", + "sphinx-design", + "sphinx-autoapi", + "sphinx-favicon", + "sphinx-copybutton", "pydata-sphinx-theme", ] [project.urls] -Homepage = "https://github.com/ROVI-org/thevenin" -Documentation = "https://rovi-org.github.io/thevenin/" -Repository = "https://github.com/ROVI-org/thevenin" -Issues = "https://github.com/ROVI-org/thevenin/issues" +Homepage = "https://github.com/NREL/thevenin" +Documentation = "https://thevenin.readthedocs.io" +Repository = "https://github.com/NREL/thevenin" +Issues = "https://github.com/NREL/thevenin/issues" diff --git a/src/thevenin/__init__.py b/src/thevenin/__init__.py index 8d5d006..8768470 100644 --- a/src/thevenin/__init__.py +++ b/src/thevenin/__init__.py @@ -4,14 +4,16 @@ The Thevenin equivalent circuit model is a common low-fidelity battery model consisting of a single resistor in series with any number of RC pairs, i.e., parallel resistor-capacitor pairs. This Python package contains an API for -building and running experiments using Thevenin models. +building and running experiments using Thevenin models. When referring to the +model itself, we use capitalized "Thevenin", and for the package lowercase +``thevenin``. -Accessing the documentation +Accessing the Documentation --------------------------- Documentation is accessible via Python's ``help()`` function which prints docstrings from a package, module, function, class, etc. You can also access -the documentation by visiting the website, hosted through GitHub pages. The -website includes search functionality and more detailed examples. +the documentation by visiting the website, hosted on Read the Docs. The website +includes search functionality and more detailed examples. """ diff --git a/src/thevenin/_experiment.py b/src/thevenin/_experiment.py index 5dd8f69..163b1e8 100644 --- a/src/thevenin/_experiment.py +++ b/src/thevenin/_experiment.py @@ -48,9 +48,9 @@ def __repr__(self) -> str: # pragma: no cover keys = ['num_steps', 'options'] values = [self.num_steps, self._options] - summary = "\n\t".join(f"{k}={v}," for k, v in zip(keys, values)) + summary = "\n ".join(f"{k}={v}," for k, v in zip(keys, values)) - readable = f"Experiment(\n\t{summary}\n)" + readable = f"Experiment(\n {summary}\n)" return readable diff --git a/src/thevenin/_ida_solver.py b/src/thevenin/_ida_solver.py index 1a3e7c4..5b158c1 100644 --- a/src/thevenin/_ida_solver.py +++ b/src/thevenin/_ida_solver.py @@ -1,456 +1,9 @@ -from __future__ import annotations -from typing import Callable +from sksundae import ida -import numpy as np -from scikits_odes_sundials import ida +class IDAResult(ida.IDAResult): + pass -class SolverReturn: - """Solver return.""" - def __init__(self, solution: ida.SolverReturn) -> None: - """ - A class to wrap the returned arrays and status of the IDASolver. - Attributes are intentionally "hidden" and accessed via read-only - properties to avoid unintentional overwrites. - - Parameters - ---------- - solution : ida.SolverReturn - The default SolverReturn class from scikits.odes. - - """ - - self._success = solution.flag >= 0 - self._message = solution.message - self._t = solution.values.t - self._y = solution.values.y - self._ydot = solution.values.ydot - self._roots = solution.roots.t is not None - self._tstop = solution.tstop.t is not None - self._errors = solution.errors.t is not None - - labels = [] - times = np.array([]) - - if self.roots: - labels.append('roots') - times = np.hstack([times, solution.roots.t]) - if self.tstop: - labels.append('tstop') - times = np.hstack([times, solution.tstop.t]) - if self.errors: - labels.append('errors') - times = np.hstack([times, solution.errors.t]) - - if len(labels) != 0: - sorted_times = sorted(set(times), reverse=True) - mapping = {t: -i-1 for i, t in enumerate(sorted_times)} - order = [mapping[t] for t in times] - - sorted_pairs = sorted(zip(order, labels)) - - for i, label in sorted_pairs: - setattr(self, '_' + label, (True, i)) - - new_line = getattr(solution, label) - if self.t[-1] < new_line.t: - self._t = np.hstack([self._t, new_line.t]) - self._y = np.vstack([self._y, new_line.y]) - self._ydot = np.vstack([self._ydot, new_line.ydot]) - - def __repr__(self) -> str: # pragma: no cover - """ - Return a readable repr string. - - Returns - ------- - readable : str - A console-readable instance representation. - - """ - - keys = ['success', 'message', 'roots', 'tstop', 'errors'] - values = [getattr(self, k) for k in keys] - - summary = "\n\t".join([f"{k}={v!r}," for k, v in zip(keys, values)]) - - readable = f"SolverReturn(\n\t{summary}\n)" - - return readable - - @property - def success(self) -> bool: - """ - Overall solver exit status. - - Returns - ------- - success : bool - True if no errors, False otherwise. - - """ - return self._success - - @property - def message(self) -> str: - """ - Readable solver exit message. - - Returns - ------- - message : str - Exit message from the IDASolver. - - """ - return self._message - - @property - def t(self) -> np.ndarray: - """ - Saved solution times. - - Returns - ------- - t : 1D np.array - Solution times [s]. - - """ - return self._t - - @property - def y(self) -> np.ndarray: - """ - Solution variables [units]. Rows correspond to solution times and - columns to state variables, in the same order as y0. - - Returns - ------- - y : 2D np.array - Solution variables [units]. - - """ - return self._y - - @property - def ydot(self) -> np.ndarray: - """ - Solution variable time derivatives [units/s]. Rows and columns share - the same organization as y. - - Returns - ------- - ydot : 2D np.array - Solution variable time derivatives [units/s]. - - """ - return self._ydot - - @property - def roots(self) -> bool | tuple: - """ - Details regarding whether or not a rootfn stopped the solver. - - Returns - ------- - roots : bool | tuple - If a rootfn stopped the solver, this value will be a tuple. The - first argument will be True, and the second argument will provide - the index within t, y, and ydot that stores the values of time - and solution when the root function was triggered. If a root did - not stop the solver, this value will be False. - - """ - return self._roots - - @property - def tstop(self) -> bool | tuple: - """ - Details regarding whether or not the tstop option stopped the solver. - - Returns - ------- - tstop : bool | tuple - If the tstop option stopped the solver, this value is a tuple. The - first argument will be True, and the second argument will provide - the index within t, y, and ydot that stores the values of time - and solution when the tstop function was triggered. If tstop did - not stop the solver, this value will be False. - - """ - return self._tstop - - @property - def errors(self) -> bool | tuple: - """ - Details regarding whether or not an error stopped the solver. - - Returns - ------- - errors : bool | tuple - If an error stopped the solver, this value will be a tuple. The - first argument will be True, and the second argument will provide - the index within t, y, and ydot that stores the values of time - and solution when the error was triggered. If an error did not - stop the solver, this value will be False. - - """ - return self._errors - - -class IDASolver: - """ - ODE/DAE solver. - - This solver supports first-order ODEs and DAEs. The solver requires the - problem to be written in terms of a residual function, with a signature - ``def residuals(t, y, yp, res, inputs) -> None``. Instead of a return - value, the function fills ``res`` (a 1D array sized like ``y``) with - expressions from the system of equations, ``res = M(y)*yp - f(t, y)``. - Here, ``t`` is time, ``y`` is an array of dependent solution variables, - and ``yp`` are time derivatives of ``y``. The ``inputs`` argument allows - the user to pass any additional parameters to the residuals function. - - Parameters - ---------- - residuals : Callable - Function like ``def residuals(t, y, yp, res, inputs) -> None``. - **kwargs : dict, optional - Keywords, descriptions, and defaults given below. - - =========== ================================================= - Key Description (*type* or {options}, default) - =========== ================================================= - atol absolute tolerance (*float*, 1e-6) - rtol relative tolerance (*float*, 1e-5) - inputs optional residual arguments (*tuple*, None) - linsolver linear solver ({'dense', 'band'}, 'dense') - lband residual function's lower bandwidth (*int*, 0) - uband residual function's upper bandwidth (*int*, 0) - rootfn root/event function (*Callable*, None) - nr_rootfns number of events in rootfn (*int*, 0) - initcond uncertain t0 values ({'y0', 'yp0', None}, 'yp0') - algidx algebraic variable indices (*list[int]*, None) - max_dt maximum allowable integration step (*float*, 0.) - tstop maximum integration time (*float*, None) - =========== ================================================= - - Notes - ----- - * IDA stands for Implicit Differential Algebraic solver. The solver is - accessed through `scikits-odes`_, a Python wrapper for `SUNDIALS`_. - * Not setting ``algidx`` for DAEs will likely result in an instability. - * For unrestricted integration steps, use ``max_dt = 0.``. - * Root functions require a signature like ``def rootfn(t, y, yp, events, - inputs) -> None``. Instead of a return value, the function fills the - ``events`` argument (a 1D array with size equal to the number of events - to track). If any ``events`` index equals zero during integration, the - solver will exit. - * If setting ``rootfn``, you also need to set ``nr_rootfns`` to allocate - memory for the correct number of expressions (i.e., ``events.size``). - - .. _SUNDIALS: https://sundials.readthedocs.io/ - .. _scikits-odes: https://bmcage.github.io/odes/dev/ - - Examples - -------- - The following demonstrates solving a system of ODEs. For ODEs, derivative - expressions ``yp`` can be written for each ``y``. Therefore, we can write - each residual as ``res[i] = yp[i] - f(t, y)`` where ``f(t, y)`` is an - expression for the derivative in terms of ``t`` and ``y``. - - Note that even though the solver requires knowing the initial derivatives, - we set ``yp0 = np.zeros_like(y0)``, which are not true ``yp0`` values. The - default option ``initcond='yp0'`` solves for the correct ``yp0`` values - before starting the integration. - - .. code-block:: python - - import thevenin - import numpy as np - import matplotlib.pyplot as plt - - def residuals(t, y, yp, res): - res[0] = yp[0] - y[1] - res[1] = yp[1] - 1e3*(1. - y[0]**2)*y[1] + y[0] - - solver = thevenin.IDASolver(residuals) - - y0 = np.array([0.5, 0.5]) - yp0 = np.zeros_like(y0) - tspan = np.linspace(0., 500., 200) - - solution = solver.solve(tspan, y0, yp0) - - plt.plot(solution.t, solution.y) - plt.show() - - The next problem solves a DAE system. DAEs arise when systems of governing - equations contain both ODEs and algebraic constraints. - - To solve a DAE, you should specify the ``y`` indices that store algebraic - variables. In other words, for which ``y`` can you not write a ``yp`` - expression? In the example below, we have ``yp[0]`` and ``yp[1]`` filling - the first two residual expressions. However, ``yp[2]`` does not appear in - any of the residuals. Therefore, ``y[2]`` is an algebraic variable, and we - tell this to the solver using the keyword argument ``algidx=[2]``. Even - though we only have one algebraic variable, this option input must be a - list of integers. - - As in the ODE example, we let the solver determine the ``yp0`` values - that provide a consistent initial condition. Prior to plotting, ``y[1]`` - is scaled for visual purposes. You can see the same example provided by - `MATLAB`_. - - .. code-block:: python - - import thevenin - import numpy as np - import matplotlib.pyplot as plt - - def residuals(t, y, yp, res): - res[0] = yp[0] + 0.04*y[0] - 1e4*y[1]*y[2] - res[1] = yp[1] - 0.04*y[0] + 1e4*y[1]*y[2] + 3e7*y[1]**2 - res[2] = y[0] + y[1] + y[2] - 1. - - solver = thevenin.IDASolver(residuals, algidx=[2]) - - y0 = np.array([1., 0., 0.]) - yp0 = np.zeros_like(y0) - tspan = np.hstack([0., 4.*np.logspace(-6, 6)]) - - solution = solver.solve(tspan, y0, yp0) - - solution.y[:, 1] *= 1e4 - - plt.semilogx(solution.t, solution.y) - plt.show() - - .. _MATLAB: - https://mathworks.com/help/matlab/math/ - solve-differential-algebraic-equations-daes.html - - """ - - __slots__ = ('_integrator', '_kwargs',) - - def __init__(self, residuals: Callable, **kwargs) -> None: - - # Default kwargs - kwargs.setdefault('atol', 1e-6) - kwargs.setdefault('rtol', 1e-5) - kwargs.setdefault('inputs', None) - kwargs.setdefault('linsolver', 'dense') - kwargs.setdefault('lband', 0) - kwargs.setdefault('uband', 0) - kwargs.setdefault('rootfn', None) - kwargs.setdefault('nr_rootfns', 0) - kwargs.setdefault('initcond', 'yp0') - kwargs.setdefault('algidx', None) - kwargs.setdefault('max_dt', 0.) - kwargs.setdefault('tstop', None) - - self._kwargs = kwargs.copy() - - # Map renamed scikits.odes options, and force new api - options = { - 'user_data': kwargs.pop('inputs'), - 'compute_initcond': kwargs.pop('initcond'), - 'algebraic_vars_idx': kwargs.pop('algidx'), - 'max_step_size': kwargs.pop('max_dt'), - 'old_api': False, - } - - options = {**options, **kwargs} - - self._integrator = ida.IDA(residuals, **options) - - def __repr__(self) -> str: # pragma: no cover - """ - Return a readable repr string. - - Returns - ------- - readable : str - A console-readable instance representation. - - """ - - items = list(self._kwargs.items()) - - summary = "\n\t".join([f"{k}={v!r}," for k, v in items]) - - readable = f"IDASolver(\n\t{summary}\n)" - - return readable - - def init_step(self, t0: float, y0: np.ndarray, - ydot0: np.ndarray) -> SolverReturn: - """ - Solve for a consistent initial condition. - - Parameters - ---------- - t0 : float - Initial time [s]. - y0 : 1D np.array - State variables at t0. - yp0 : 1D np.array - State variable time derivatives at t0. - - Returns - ------- - solution : SolverReturn - Solution at time t0. - - """ - - solution = self._integrator.init_step(t0, y0, ydot0) - return SolverReturn(solution) - - def step(self, t: float) -> SolverReturn: - """ - Solve for a successive time step. - - Before calling step() for the first time, call init_step() to - initialize the solver at 't0'. - - Parameters - ---------- - t : float - Solution step time [s]. Can be higher or lower than the previous - time, however, significantly lower values may return errors. - - Returns - ------- - solution : SolverReturn - Solution at time t. - - """ - - solution = self._integrator.step(t) - return SolverReturn(solution) - - def solve(self, tspan: np.ndarray, y0: np.ndarray, - ydot0: np.ndarray) -> SolverReturn: - """ - Solve the system over 'tspan'. - - Parameters - ---------- - tspan : 1D np.array - Times [s] to store the solution. - y0 : 1D np.array - State variables at tspan[0]. - yp0 : 1D np.array - State variable time derivatives at tspan[0]. - - Returns - ------- - solution : SolverReturn - Solution at times in tspan. - - """ - - solution = self._integrator.solve(tspan, y0, ydot0) - return SolverReturn(solution) +class IDASolver(ida.IDA): + pass diff --git a/src/thevenin/_model.py b/src/thevenin/_model.py index 6321c8a..6f88aac 100644 --- a/src/thevenin/_model.py +++ b/src/thevenin/_model.py @@ -135,9 +135,9 @@ def __repr__(self) -> str: # pragma: no cover keys = self._repr_keys values = [getattr(self, k) for k in keys] - summary = "\n\t".join([f"{k}={v}," for k, v in zip(keys, values)]) + summary = "\n ".join([f"{k}={v}," for k, v in zip(keys, values)]) - readable = f"Model(\n\t{summary}\n)" + readable = f"Model(\n {summary}\n)" return readable @@ -298,7 +298,7 @@ def residuals(self, t: float, sv: np.ndarray, svdot: np.ndarray, Returns ------- res : 1D np.array - DAE residuals, res = M*ydot - rhs(t, y). + DAE residuals, res = M*yp - rhs(t, y). """ return self._mass_matrix.dot(svdot) - self.rhs_funcs(t, sv, inputs) @@ -353,8 +353,9 @@ def run_step(self, exp: Experiment, stepidx: int) -> StepSolution: value = step['value'] step['value'] = lambda t: value - kwargs['inputs'] = step - kwargs['algidx'] = self._algidx + kwargs['userdata'] = step + kwargs['calc_initcond'] = 'yp0' + kwargs['algebraic_idx'] = self._algidx if step['limits'] is not None: _setup_rootfn(step['limits'], kwargs) @@ -369,7 +370,7 @@ def run_step(self, exp: Experiment, stepidx: int) -> StepSolution: self._t0 = soln.t[-1] self._sv0 = soln.y[-1].copy() - self._svdot0 = soln.ydot[-1].copy() + self._svdot0 = soln.yp[-1].copy() return soln @@ -429,7 +430,7 @@ def _residuals(self, t: float, sv: np.ndarray, svdot: np.ndarray, svdot : 1D np.array State variable time derivatives at time t. res : 1D np.array - DAE residuals, res = M*ydot - rhs(t, y). + DAE residuals, res = M*yp - rhs(t, y). inputs : dict Dictionary detailing an experimental step. @@ -445,8 +446,6 @@ def _residuals(self, t: float, sv: np.ndarray, svdot: np.ndarray, class _RootFunction: """Root function callables.""" - __slots__ = ('keys', 'values', 'size',) - def __init__(self, limits: tuple[str, float]) -> None: """ This class is a generalize root function callable. All possible root @@ -523,8 +522,8 @@ def _setup_rootfn(limits: tuple[str, float], kwargs: dict) -> None: rootfn = _RootFunction(limits) - kwargs['rootfn'] = rootfn - kwargs['nr_rootfns'] = rootfn.size + kwargs['eventsfn'] = rootfn + kwargs['num_events'] = rootfn.size def _yaml_reader(file: str) -> dict: @@ -585,7 +584,7 @@ def eval_constructor(loader, node): def formatwarning(message, category, filename, lineno, line=None): - return f"\n[thevenin {category.__name__}]: {message}\n\n" + return f"\n[thevenin {category.__name__}] {message}\n\n" def short_warn(message, category=None, stacklevel=1, source=None): diff --git a/src/thevenin/_solutions.py b/src/thevenin/_solutions.py index 159f09e..7f5d082 100644 --- a/src/thevenin/_solutions.py +++ b/src/thevenin/_solutions.py @@ -1,19 +1,19 @@ from __future__ import annotations from typing import TYPE_CHECKING - from copy import deepcopy +import textwrap import numpy as np import matplotlib.pyplot as plt from scipy.integrate import cumulative_trapezoid -from ._ida_solver import SolverReturn +from ._ida_solver import IDAResult if TYPE_CHECKING: # pragma: no cover from ._model import Model -class BaseSolution(SolverReturn): +class BaseSolution(IDAResult): """Base solution.""" def __init__(self) -> None: @@ -38,7 +38,33 @@ def __repr__(self) -> str: # pragma: no cover A console-readable instance representation. """ - return repr(self.vars.keys()) + + def wrap_string(value: list, width: int, indent: int): + if not isinstance(value, list): + value = list(value) + + indent = ' '*indent + + text = "[" + ", ".join(f"{v!r}" for v in value) + "]" + + return textwrap.fill(text, width=width, subsequent_indent=indent) + + vars = wrap_string(self.vars.keys(), 70, len(' vars=[')) + + data = { + 'solvetime': self.solvetime, + 'success': self.success, + 'status': self.status, + 'nfev': self.nfev, + 'njev': self.njev, + 'vars': vars, + } + + summary = "\n ".join(f"{k}={v}," for k, v in data.items()) + + readable = f"{self.__class__.__name__}(\n {summary}\n)" + + return readable def plot(self, x: str, y: str, **kwargs) -> None: """ @@ -75,7 +101,7 @@ def plot(self, x: str, y: str, **kwargs) -> None: plt.xlabel(xlabel) plt.ylabel(ylabel) - plt.show(block=False) + plt.show() def _to_dict(self) -> None: """ @@ -128,7 +154,7 @@ def _to_dict(self) -> None: class StepSolution(BaseSolution): """Single-step solution.""" - def __init__(self, model: Model, ida_soln: SolverReturn, + def __init__(self, model: Model, ida_soln: IDAResult, timer: float) -> None: """ A solution instance for a single experimental step. @@ -148,14 +174,21 @@ def __init__(self, model: Model, ida_soln: SolverReturn, self._model = deepcopy(model) - self._success = ida_soln.success - self._message = ida_soln.message - self._t = ida_soln.t - self._y = ida_soln.y - self._ydot = ida_soln.ydot - self._roots = ida_soln.roots - self._tstop = ida_soln.tstop - self._errors = ida_soln.errors + self.message = ida_soln.message + self.success = ida_soln.success + self.status = ida_soln.status + + self.t = ida_soln.t + self.y = ida_soln.y + self.yp = ida_soln.yp + + self.i_events = ida_soln.i_events + self.t_events = ida_soln.t_events + self.y_events = ida_soln.y_events + self.yp_events = ida_soln.yp_events + + self.nfev = ida_soln.nfev + self.njev = ida_soln.njev self._timer = timer @@ -172,7 +205,7 @@ def solvetime(self) -> str: An f-string with the solver integration time in seconds. """ - return f"Solve time: {self._timer:.3f} s" + return f"{self._timer:.3f} s" class CycleSolution(BaseSolution): @@ -199,30 +232,55 @@ def __init__(self, *soln: StepSolution) -> None: sv_size = self._model._sv0.size - self._success = [] - self._message = [] - self._t = np.empty([0]) - self._y = np.empty([0, sv_size]) - self._ydot = np.empty([0, sv_size]) - self._roots = [] - self._tstop = [] - self._errors = [] + self.message = [] + self.success = [] + self.status = [] + + self.t = np.empty([0]) + self.y = np.empty([0, sv_size]) + self.yp = np.empty([0, sv_size]) + + self.t_events = None + self.y_events = None + self.yp_events = None + + self.nfev = [] + self.njev = [] + self._timers = [] for soln in self._solns: - if self._t.size > 0: - shifted_times = self._t[-1] + soln.t + 1e-3 + if self.t.size > 0: + shift_t = self.t[-1] + soln.t + 1e-3 else: - shifted_times = soln.t - - self._success.append(soln.success) - self._message.append(soln.message) - self._t = np.hstack([self._t, shifted_times]) - self._y = np.vstack([self._y, soln.y]) - self._ydot = np.vstack([self._ydot, soln.ydot]) - self._roots.append(soln.roots) - self._tstop.append(soln.tstop) - self._errors.append(soln.errors) + shift_t = soln.t + + if soln.t_events and self.t.size > 0: + shift_t_events = self.t[-1] + soln.t_events + 1e-3 + elif soln.t_events: + shift_t_events = soln.t_events + + self.message.append(soln.message) + self.success.append(soln.success) + self.status.append(soln.status) + + self.t = np.hstack([self.t, shift_t]) + self.y = np.vstack([self.y, soln.y]) + self.yp = np.vstack([self.yp, soln.yp]) + + if soln.t_events: + if self.t_events is None: + self.t_events = shift_t_events + self.y_events = soln.y_events + self.yp_events = soln.yp_events + else: + self.t_events = np.hstack([self.t_events, shift_t_events]) + self.y_events = np.vstack([soln.y_events]) + self.yp_events = np.vstack([soln.yp_events]) + + self.nfev.append(soln.nfev) + self.njev.append(soln.njev) + self._timers.append(soln._timer) self._to_dict() @@ -238,7 +296,7 @@ def solvetime(self) -> str: An f-string with the total solver integration time in seconds. """ - return f"Solve time: {sum(self._timers):.3f} s" + return f"{sum(self._timers):.3f} s" def get_steps(self, idx: int | tuple) -> StepSolution | CycleSolution: """ diff --git a/tests/test_experiment.py b/tests/test_experiment.py index e8dc088..80e2195 100644 --- a/tests/test_experiment.py +++ b/tests/test_experiment.py @@ -1,11 +1,11 @@ import pytest -import thevenin import numpy as np +import thevenin as thev @pytest.fixture(scope='function') def expr(): - return thevenin.Experiment() + return thev.Experiment() def test_initialization(expr): diff --git a/tests/test_ida_solver.py b/tests/test_ida_solver.py index 69b440f..3f219c9 100644 --- a/tests/test_ida_solver.py +++ b/tests/test_ida_solver.py @@ -1,9 +1,8 @@ import pytest -import thevenin import numpy as np +import thevenin as thev -from scikits_odes_sundials import ida -from thevenin._ida_solver import SolverReturn +from thevenin._ida_solver import IDASolver @pytest.fixture(scope='function') @@ -11,105 +10,36 @@ def dummy_soln(): def residuals(t, y, yp, res): res[0] = yp[0] - solver = ida.IDA(residuals) + solver = IDASolver(residuals) dummy_soln = solver.solve(np.linspace(0., 10., 11), [1.], [0.]) return dummy_soln @pytest.fixture(scope='function') -def root_soln(): - def rootfn(t, y, yp, events): +def events_soln(): + def eventsfn(t, y, yp, events): events[0] = y[0] - 0.5 def residuals(t, y, yp, res): res[0] = yp[0] + 0.1 - solver = ida.IDA(residuals, rootfn=rootfn, nr_rootfns=1) - root_soln = solver.solve(np.linspace(0., 10., 11), [1.], [0.]) + solver = IDASolver(residuals, eventsfn=eventsfn, num_events=1) + events_soln = solver.solve(np.linspace(0., 10., 11), [1.], [0.]) - return root_soln - - -@pytest.fixture(scope='function') -def tstop_soln(): - def residuals(t, y, yp, res): - res[0] = yp[0] - - solver = ida.IDA(residuals, tstop=4.5) - tstop_soln = solver.solve(np.linspace(0., 10., 11), [1.], [0.]) - - return tstop_soln - - -@pytest.fixture(scope='function') -def error_soln(): - def residuals(t, y, yp, res): - res[0] = 0. - - solver = ida.IDA(residuals) - error_soln = solver.solve(np.linspace(0., 10., 11), [1.], [0.]) - - return error_soln - - -@pytest.fixture(scope='function') -def stacked_soln(tstop_soln, root_soln): - - stacked_soln = ida.SolverReturn( - tstop_soln.flag, tstop_soln.values, tstop_soln.errors, - root_soln.roots, tstop_soln.tstop, tstop_soln.message, - ) - - return stacked_soln + return events_soln def test_solver_return(dummy_soln): - solution = SolverReturn(dummy_soln) - - assert solution.success - assert not solution.roots - assert not solution.tstop - assert not solution.errors - - assert solution.message == dummy_soln.message - assert np.allclose(solution.t, dummy_soln.values.t) - assert np.allclose(solution.y, dummy_soln.values.y) - assert np.allclose(solution.ydot, dummy_soln.values.ydot) - - -def test_solver_return_roots(root_soln): - solution = SolverReturn(root_soln) - - assert solution.success - assert solution.roots[0] - assert np.allclose(solution.y[-1], root_soln.roots.y) - - -def test_solver_return_tstop(tstop_soln): - solution = SolverReturn(tstop_soln) - - assert solution.success - assert solution.tstop[0] - assert np.allclose(solution.y[-1], tstop_soln.tstop.y) - - -def test_solver_return_errors(error_soln): - solution = SolverReturn(error_soln) - - assert not solution.success - assert solution.errors[0] - assert np.allclose(solution.y[-1], error_soln.errors.y) + assert dummy_soln.success + assert not dummy_soln.t_events -def test_solver_return_event_stack(stacked_soln): - solution = SolverReturn(stacked_soln) - assert solution.tstop[0] - assert solution.tstop[-1] == -2 +def test_solver_return_roots(events_soln): - assert solution.roots[0] - assert solution.roots[-1] == -1 + assert events_soln.success + assert events_soln.t_events def test_ida_solver_with_ode(): @@ -117,7 +47,7 @@ def residuals(t, y, yp, res): res[0] = yp[0] - y[1] res[1] = yp[1] - 1e3*(1. - y[0]**2)*y[1] + y[0] - solver = thevenin.IDASolver(residuals) + solver = thev.IDASolver(residuals) y0 = np.array([0.5, 0.5]) yp0 = np.zeros_like(y0) @@ -142,7 +72,7 @@ def residuals(t, y, yp, res): res[1] = yp[1] - 0.04*y[0] + 1e4*y[1]*y[2] + 3e7*y[1]**2 res[2] = y[0] + y[1] + y[2] - 1. - solver = thevenin.IDASolver(residuals, max_dt=0.) + solver = thev.IDASolver(residuals, max_step=0.) y0 = np.array([1., 0., 0.]) yp0 = np.zeros_like(y0) diff --git a/tests/test_model.py b/tests/test_model.py index 8253e2b..2304747 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,8 +1,8 @@ import warnings import pytest -import thevenin import numpy as np +import thevenin as thev @pytest.fixture(scope='function') @@ -29,12 +29,12 @@ def dict_params(): @pytest.fixture(scope='function') def model_0RC(dict_params): - return thevenin.Model(dict_params) + return thev.Model(dict_params) @pytest.fixture(scope='function') def model_1RC(dict_params): - model = thevenin.Model(dict_params) + model = thev.Model(dict_params) model.num_RC_pairs = 1 model.R1 = lambda soc, T_cell: 0.01 + 0.01*soc - T_cell/3e4 @@ -47,7 +47,7 @@ def model_1RC(dict_params): @pytest.fixture(scope='function') def model_2RC(dict_params): - model = thevenin.Model(dict_params) + model = thev.Model(dict_params) model.num_RC_pairs = 2 model.R1 = lambda soc, T_cell: 0.01 + 0.01*soc - T_cell/3e4 @@ -62,7 +62,7 @@ def model_2RC(dict_params): @pytest.fixture(scope='function') def constant_steps(): - expr = thevenin.Experiment() + expr = thev.Experiment() expr.add_step('current_A', 1., (3600., 1.), limits=('voltage_V', 3.)) expr.add_step('current_A', 0., (600., 1.)) expr.add_step('current_A', -1., (3600., 1.), limits=('voltage_V', 4.3)) @@ -76,7 +76,7 @@ def constant_steps(): def dynamic_current(): def load(t): return np.sin(2.*np.pi*t / 120.) - expr = thevenin.Experiment() + expr = thev.Experiment() expr.add_step('current_A', load, (600., 1.)) return expr @@ -86,7 +86,7 @@ def load(t): return np.sin(2.*np.pi*t / 120.) def dynamic_voltage(): def load(t): return 3.8 + 10e-3*np.sin(2.*np.pi*t / 120.) - expr = thevenin.Experiment() + expr = thev.Experiment() expr.add_step('voltage_V', load, (600., 1.)) return expr @@ -96,7 +96,7 @@ def load(t): return 3.8 + 10e-3*np.sin(2.*np.pi*t / 120.) def dynamic_power(): def load(t): return np.sin(2.*np.pi*t / 120.) - expr = thevenin.Experiment() + expr = thev.Experiment() expr.add_step('power_W', load, (600., 1.)) return expr @@ -106,12 +106,12 @@ def test_bad_initialization(dict_params): # wrong params type with pytest.raises(TypeError): - _ = thevenin.Model(['wrong_type']) + _ = thev.Model(['wrong_type']) # invalid/excess key/value pairs with pytest.raises(ValueError): dict_params['fake'] = 'parameter' - _ = thevenin.Model(dict_params) + _ = thev.Model(dict_params) def test_model_w_yaml_input(constant_steps, dynamic_current, dynamic_voltage, @@ -119,19 +119,19 @@ def test_model_w_yaml_input(constant_steps, dynamic_current, dynamic_voltage, # using default file with pytest.warns(UserWarning): - model = thevenin.Model() + model = thev.Model() # using default file by name with pytest.warns(UserWarning): - model = thevenin.Model('params') + model = thev.Model('params') # using default file by name w/ extension with pytest.warns(UserWarning): - model = thevenin.Model('params.yaml') + model = thev.Model('params.yaml') soln = model.run(constant_steps) assert soln.success - assert any(soln.roots) + # assert any(soln.i_events) soln = model.run(dynamic_current) assert soln.success @@ -147,11 +147,11 @@ def test_bad_yaml_inputs(): # only .yaml extensions with pytest.raises(ValueError): - _ = thevenin.Model('fake.fake') + _ = thev.Model('fake.fake') # file doesn't exist with pytest.raises(FileNotFoundError): - _ = thevenin.Model('fake') + _ = thev.Model('fake') def test_run_step(model_2RC, constant_steps): @@ -176,15 +176,15 @@ def test_model_w_multistep_experiment(model_0RC, model_1RC, model_2RC, soln = model_0RC.run(constant_steps) assert soln.success - assert any(soln.roots) + assert any(status == 2 for status in soln.status) soln = model_1RC.run(constant_steps) assert soln.success - assert any(soln.roots) + assert any(status == 2 for status in soln.status) soln = model_2RC.run(constant_steps) assert soln.success - assert any(soln.roots) + assert any(status == 2 for status in soln.status) def test_model_w_dynamic_current(model_0RC, model_1RC, model_2RC, @@ -228,7 +228,7 @@ def test_model_w_dynamic_power(model_0RC, model_1RC, model_2RC, def test_resting_experiment(model_2RC): - expr = thevenin.Experiment() + expr = thev.Experiment() expr.add_step('current_A', 0., (100., 1.)) soln = model_2RC.run(expr) @@ -319,7 +319,7 @@ def test_custom_format(): original = warnings.formatwarning(*args).strip() # custom format works - assert custom == "[thevenin Warning]: This is a test warning." + assert custom == "[thevenin Warning] This is a test warning." # warnings from warnings.warn not impacted by custom format - assert original != "[thevenin Warning]: This is a test warning." + assert original != "[thevenin Warning] This is a test warning." diff --git a/tests/test_solutions.py b/tests/test_solutions.py index 22376b5..c63ac99 100644 --- a/tests/test_solutions.py +++ b/tests/test_solutions.py @@ -1,8 +1,8 @@ import warnings import pytest -import thevenin import numpy as np +import thevenin as thev import matplotlib.pyplot as plt @@ -11,9 +11,9 @@ def soln(): warnings.filterwarnings('ignore') - model = thevenin.Model() + model = thev.Model() - expr = thevenin.Experiment() + expr = thev.Experiment() expr.add_step('current_A', 1., (3600., 1.), limits=('voltage_V', 3.)) expr.add_step('current_A', 0., (3600., 1.)) @@ -33,9 +33,10 @@ def test_step_and_cycle_solutions(soln): step_soln.plot('fake', 'plot') # plots w/ and w/o units - step_soln.plot('soc', 'soc') - step_soln.plot('time_h', 'voltage_V') - plt.close('all') + with plt.ion(): + step_soln.plot('soc', 'soc') + step_soln.plot('time_h', 'voltage_V') + plt.close('all') # solvetime works and times stacked correctly cycle_soln = soln.get_steps((0, 1)) @@ -47,6 +48,7 @@ def test_step_and_cycle_solutions(soln): cycle_soln.plot('fake', 'plot') # plots w/ and w/o units - cycle_soln.plot('soc', 'soc') - cycle_soln.plot('time_h', 'voltage_V') - plt.close('all') + with plt.ion(): + cycle_soln.plot('soc', 'soc') + cycle_soln.plot('time_h', 'voltage_V') + plt.close('all')