pydma 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pydma-0.1.0/LICENSE +29 -0
- pydma-0.1.0/PKG-INFO +271 -0
- pydma-0.1.0/README.md +226 -0
- pydma-0.1.0/pyproject.toml +96 -0
- pydma-0.1.0/setup.cfg +4 -0
- pydma-0.1.0/src/pydma/__init__.py +124 -0
- pydma-0.1.0/src/pydma/analysis/__init__.py +14 -0
- pydma-0.1.0/src/pydma/analysis/degradation.py +259 -0
- pydma-0.1.0/src/pydma/analysis/dva.py +154 -0
- pydma-0.1.0/src/pydma/analysis/ica.py +166 -0
- pydma-0.1.0/src/pydma/core/__init__.py +14 -0
- pydma-0.1.0/src/pydma/core/analyzer.py +1168 -0
- pydma-0.1.0/src/pydma/core/objectives.py +948 -0
- pydma-0.1.0/src/pydma/core/optimizer.py +382 -0
- pydma-0.1.0/src/pydma/electrodes/__init__.py +7 -0
- pydma-0.1.0/src/pydma/electrodes/blend.py +280 -0
- pydma-0.1.0/src/pydma/electrodes/electrode.py +318 -0
- pydma-0.1.0/src/pydma/electrodes/inhomogeneity.py +200 -0
- pydma-0.1.0/src/pydma/preprocessing/__init__.py +19 -0
- pydma-0.1.0/src/pydma/preprocessing/loader.py +538 -0
- pydma-0.1.0/src/pydma/preprocessing/smoother.py +365 -0
- pydma-0.1.0/src/pydma/silicon/__init__.py +8 -0
- pydma-0.1.0/src/pydma/silicon/generator.py +468 -0
- pydma-0.1.0/src/pydma/utils/__init__.py +24 -0
- pydma-0.1.0/src/pydma/utils/dma_config.py +563 -0
- pydma-0.1.0/src/pydma/utils/results.py +771 -0
- pydma-0.1.0/src/pydma/utils/roi.py +143 -0
- pydma-0.1.0/src/pydma/visualization/__init__.py +23 -0
- pydma-0.1.0/src/pydma/visualization/plots.py +1478 -0
- pydma-0.1.0/src/pydma.egg-info/PKG-INFO +271 -0
- pydma-0.1.0/src/pydma.egg-info/SOURCES.txt +32 -0
- pydma-0.1.0/src/pydma.egg-info/dependency_links.txt +1 -0
- pydma-0.1.0/src/pydma.egg-info/requires.txt +21 -0
- pydma-0.1.0/src/pydma.egg-info/top_level.txt +1 -0
pydma-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, PyDMA contributors
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
pydma-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pydma
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Battery Degradation Mode Analysis - Python implementation of TUM-EES DegradationModeAnalysis
|
|
5
|
+
Author-email: TUM-EES <mathias.rehm@tum.de>
|
|
6
|
+
Maintainer-email: TUM-EES <mathias.rehm@tum.de>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
Project-URL: Homepage, https://github.com/tum-ees/pydma
|
|
9
|
+
Project-URL: Documentation, https://github.com/tum-ees/pydma#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/tum-ees/pydma.git
|
|
11
|
+
Project-URL: Issues, https://github.com/tum-ees/pydma/issues
|
|
12
|
+
Keywords: battery,degradation,lithium-ion,sodium-ion,OCV,DVA,ICA,electrochemistry,aging
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: numpy>=1.20.0
|
|
27
|
+
Requires-Dist: scipy>=1.7.0
|
|
28
|
+
Requires-Dist: pandas>=1.3.0
|
|
29
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
30
|
+
Requires-Dist: statsmodels>=0.13.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
38
|
+
Provides-Extra: docs
|
|
39
|
+
Requires-Dist: sphinx>=5.0.0; extra == "docs"
|
|
40
|
+
Requires-Dist: sphinx-rtd-theme>=1.0.0; extra == "docs"
|
|
41
|
+
Provides-Extra: notebook
|
|
42
|
+
Requires-Dist: jupyter>=1.0.0; extra == "notebook"
|
|
43
|
+
Requires-Dist: ipywidgets>=8.0.0; extra == "notebook"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# PyDMA - Battery Degradation Mode Analysis
|
|
47
|
+
|
|
48
|
+
<div align="center">
|
|
49
|
+
|
|
50
|
+
**Python implementation of TUM-EES DegradationModeAnalysis framework**
|
|
51
|
+
|
|
52
|
+
<!-- environment and language -->
|
|
53
|
+
<a href="https://www.python.org/">
|
|
54
|
+
<img src="https://img.shields.io/badge/Platform-Python-blue.svg" alt="Python">
|
|
55
|
+
</a>
|
|
56
|
+
|
|
57
|
+
<!-- license badge -->
|
|
58
|
+
<a href="https://opensource.org/licenses/BSD-3-Clause">
|
|
59
|
+
<img src="https://img.shields.io/badge/License-BSD%203--Clause-blue.svg" alt="BSD 3-Clause License">
|
|
60
|
+
</a>
|
|
61
|
+
|
|
62
|
+
<!-- paper badges -->
|
|
63
|
+
<a href="https://doi.org/10.1016/j.jpowsour.2026.239418">
|
|
64
|
+
<img src="https://img.shields.io/badge/Paper-J.%20Power%20Sources-green.svg" alt="Journal of Power Sources">
|
|
65
|
+
</a>
|
|
66
|
+
|
|
67
|
+
<a href="https://doi.org/10.1039/D5EB00221D">
|
|
68
|
+
<img src="https://img.shields.io/badge/Paper-EES%20Batteries-green.svg" alt="EES Batteries">
|
|
69
|
+
</a>
|
|
70
|
+
|
|
71
|
+
<br>
|
|
72
|
+
|
|
73
|
+
<img src="doc/OCP_shift_over_SOC.gif" width="400" alt="OCV shift over SOC animation">
|
|
74
|
+
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
## 🔭 Overview
|
|
78
|
+
|
|
79
|
+
PyDMA is a Python package for performing degradation mode analysis of lithium-ion and sodium-ion batteries. Among others, both electrodes can be modeled as blends, and inhomogeneity is available for both electrodes. It reconstructs measured pseudo-OCV curves using half-cell electrode potential curves to quantify three degradation mechanisms:
|
|
80
|
+
|
|
81
|
+
- **LLI**: Loss of lithium inventory (charge carrier loss)
|
|
82
|
+
- **LAM_an**: Loss of active material at anode
|
|
83
|
+
- **LAM_ca**: Loss of active material at cathode
|
|
84
|
+
|
|
85
|
+
The core algorithm reconstructs full-cell OCV as:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
OCV_cell(SOC) = U_cathode(α_ca · SOC + β_ca) - U_anode(α_an · SOC + β_an)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Where α scales capacity and β shifts the SOC window.
|
|
92
|
+
|
|
93
|
+
## ⚙️ Installation
|
|
94
|
+
|
|
95
|
+
PyPI release is coming soon:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# pip install pydma
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Install from source:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
git clone https://github.com/tum-ees/pydma.git
|
|
105
|
+
cd pydma
|
|
106
|
+
pip install .
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
For development installation:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
git clone https://github.com/tum-ees/pydma.git
|
|
113
|
+
cd pydma
|
|
114
|
+
pip install -e ".[dev,notebook]"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 🎮 Quick Start
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
import pydma
|
|
121
|
+
from pydma import DMAAnalyzer, DMAConfig
|
|
122
|
+
|
|
123
|
+
# Load your electrode OCP data
|
|
124
|
+
anode_ocp = pydma.load_ocp("path/to/anode_ocp.csv")
|
|
125
|
+
cathode_ocp = pydma.load_ocp("path/to/cathode_ocp.csv")
|
|
126
|
+
|
|
127
|
+
# Create analyzer with configuration
|
|
128
|
+
config = DMAConfig(
|
|
129
|
+
direction="charge",
|
|
130
|
+
weight_ocv=100,
|
|
131
|
+
weight_dva=1,
|
|
132
|
+
weight_ica=0,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
analyzer = DMAAnalyzer(
|
|
136
|
+
anode_ocp=anode_ocp,
|
|
137
|
+
cathode_ocp=cathode_ocp,
|
|
138
|
+
config=config,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Run analysis on aging study data
|
|
142
|
+
results = analyzer.analyze_aging_study(
|
|
143
|
+
pocv_data={"CU1": pocv_cu1, "CU2": pocv_cu2, ...},
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Access degradation modes
|
|
147
|
+
print(f"LLI: {results.lam_results['CU2'].lli:.2%}")
|
|
148
|
+
print(f"LAM_an: {results.lam_results['CU2'].lam_anode:.2%}")
|
|
149
|
+
print(f"LAM_ca: {results.lam_results['CU2'].lam_cathode:.2%}")
|
|
150
|
+
|
|
151
|
+
# Plot results
|
|
152
|
+
results.plot_degradation_modes()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 📖 Key Features
|
|
156
|
+
|
|
157
|
+
### Blend Electrode Model
|
|
158
|
+
|
|
159
|
+
Supports blended electrodes (e.g., Silicon-Graphite anodes):
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
config = DMAConfig(
|
|
163
|
+
use_anode_blend=True,
|
|
164
|
+
gamma_anode_blend2_upper=0.30, # Max 30% silicon
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
analyzer = DMAAnalyzer(
|
|
168
|
+
anode_blend1_ocp=graphite_ocp, # Primary: Graphite
|
|
169
|
+
anode_blend2_ocp=silicon_ocp, # Secondary: Silicon
|
|
170
|
+
cathode_ocp=cathode_ocp,
|
|
171
|
+
config=config,
|
|
172
|
+
)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Inhomogeneity Modeling
|
|
176
|
+
|
|
177
|
+
Models electrode inhomogeneity effects:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
config = DMAConfig(
|
|
181
|
+
allow_anode_inhomogeneity=True,
|
|
182
|
+
allow_cathode_inhomogeneity=True,
|
|
183
|
+
max_inhomogeneity=0.3,
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Multiple Fitting Objectives
|
|
188
|
+
|
|
189
|
+
Combine OCV, DVA, and ICA fitting with custom weights:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
config = DMAConfig(
|
|
193
|
+
weight_ocv=100,
|
|
194
|
+
weight_dva=1,
|
|
195
|
+
weight_ica=0,
|
|
196
|
+
roi_dva_min=0.1,
|
|
197
|
+
roi_dva_max=0.9,
|
|
198
|
+
)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Speed Presets
|
|
202
|
+
|
|
203
|
+
Choose optimization thoroughness:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
config = DMAConfig(speed_preset="thorough") # "fast", "medium", or "thorough"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## 🔧 Silicon OCP Generation
|
|
210
|
+
|
|
211
|
+
Generate silicon OCP from measured blend electrode data:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from pydma.silicon import generate_silicon_curve
|
|
215
|
+
|
|
216
|
+
silicon_ocp = generate_silicon_curve(
|
|
217
|
+
blend_ocp=measured_blend_ocp,
|
|
218
|
+
graphite_ocp=graphite_reference,
|
|
219
|
+
gamma_si=0.245,
|
|
220
|
+
direction="lithiation",
|
|
221
|
+
)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## 📊 Parameter Vector Layout
|
|
225
|
+
|
|
226
|
+
The optimizer uses an 8-element parameter vector internally:
|
|
227
|
+
|
|
228
|
+
| Index | Parameter | Description |
|
|
229
|
+
|-------|-----------|-------------|
|
|
230
|
+
| 0 | α_an | Anode scaling / capacity ratio |
|
|
231
|
+
| 1 | β_an | Anode offset / SOC shift |
|
|
232
|
+
| 2 | α_ca | Cathode scaling |
|
|
233
|
+
| 3 | β_ca | Cathode offset |
|
|
234
|
+
| 4 | γ_blend2_an | Anode blend2 fraction (0 if disabled) |
|
|
235
|
+
| 5 | γ_blend2_ca | Cathode blend2 fraction (0 if disabled) |
|
|
236
|
+
| 6 | σ_an | Anode inhomogeneity magnitude |
|
|
237
|
+
| 7 | σ_ca | Cathode inhomogeneity magnitude |
|
|
238
|
+
|
|
239
|
+
## 📚 Documentation
|
|
240
|
+
|
|
241
|
+
See the [Getting Started Notebook](notebooks/getting_started.ipynb) for detailed examples.
|
|
242
|
+
|
|
243
|
+
## 🎖️ Acknowledgments
|
|
244
|
+
|
|
245
|
+
This is a Python translation of the [TUM-EES DegradationModeAnalysis](https://github.com/tum-ees/degradation-mode-analysis) MATLAB framework.
|
|
246
|
+
We would like to thank Johannes Natterer for providing the aging data set of a cyclic aged P45B cell and for help in translating into Python.
|
|
247
|
+
|
|
248
|
+
## 📯 Developers
|
|
249
|
+
|
|
250
|
+
- [Mathias Rehm](mailto:mathias.rehm@tum.de), Chair of Electrical Energy Storage Technology, School of Engineering and Design, Technical University of Munich, 80333 Munich, Germany
|
|
251
|
+
- [Josef Eizenhammer](mailto:josef.eizenhammer@tum.de), Chair of Electrical Energy Storage Technology, School of Engineering and Design, Technical University of Munich, 80333 Munich, Germany
|
|
252
|
+
- Moritz Günthner (student research project)
|
|
253
|
+
- Can Korkmaz (student research project)
|
|
254
|
+
|
|
255
|
+
## ✒️ Citation
|
|
256
|
+
|
|
257
|
+
This framework is the Python implementation of the MATLAB DegradationModeAnalysis toolbox.
|
|
258
|
+
If you use this repository in any publication, please cite:
|
|
259
|
+
|
|
260
|
+
> M. Rehm et al., "How to determine the degradation modes of lithium-ion batteries with silicon–graphite blend electrodes,"
|
|
261
|
+
> *Journal of Power Sources*, 2026, DOI: [10.1016/j.jpowsour.2026.239418](https://doi.org/10.1016/j.jpowsour.2026.239418)
|
|
262
|
+
|
|
263
|
+
The framework is also applied and validated on commercial sodium-ion batteries in the following publication.
|
|
264
|
+
We appreciate citing this work as well, and kindly ask you to do so if your work involves sodium-ion cells:
|
|
265
|
+
|
|
266
|
+
> M. Rehm et al., "Aging of commercial sodium-ion batteries with layered oxides: how to measure and analyze it?,"
|
|
267
|
+
> *EES Batteries*, 2026, DOI: [10.1039/D5EB00221D](https://doi.org/10.1039/D5EB00221D)
|
|
268
|
+
|
|
269
|
+
## 📜 License
|
|
270
|
+
|
|
271
|
+
BSD 3-Clause "New" or "Revised" License - see [LICENSE](LICENSE) for details.
|
pydma-0.1.0/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# PyDMA - Battery Degradation Mode Analysis
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**Python implementation of TUM-EES DegradationModeAnalysis framework**
|
|
6
|
+
|
|
7
|
+
<!-- environment and language -->
|
|
8
|
+
<a href="https://www.python.org/">
|
|
9
|
+
<img src="https://img.shields.io/badge/Platform-Python-blue.svg" alt="Python">
|
|
10
|
+
</a>
|
|
11
|
+
|
|
12
|
+
<!-- license badge -->
|
|
13
|
+
<a href="https://opensource.org/licenses/BSD-3-Clause">
|
|
14
|
+
<img src="https://img.shields.io/badge/License-BSD%203--Clause-blue.svg" alt="BSD 3-Clause License">
|
|
15
|
+
</a>
|
|
16
|
+
|
|
17
|
+
<!-- paper badges -->
|
|
18
|
+
<a href="https://doi.org/10.1016/j.jpowsour.2026.239418">
|
|
19
|
+
<img src="https://img.shields.io/badge/Paper-J.%20Power%20Sources-green.svg" alt="Journal of Power Sources">
|
|
20
|
+
</a>
|
|
21
|
+
|
|
22
|
+
<a href="https://doi.org/10.1039/D5EB00221D">
|
|
23
|
+
<img src="https://img.shields.io/badge/Paper-EES%20Batteries-green.svg" alt="EES Batteries">
|
|
24
|
+
</a>
|
|
25
|
+
|
|
26
|
+
<br>
|
|
27
|
+
|
|
28
|
+
<img src="doc/OCP_shift_over_SOC.gif" width="400" alt="OCV shift over SOC animation">
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
## 🔭 Overview
|
|
33
|
+
|
|
34
|
+
PyDMA is a Python package for performing degradation mode analysis of lithium-ion and sodium-ion batteries. Among others, both electrodes can be modeled as blends, and inhomogeneity is available for both electrodes. It reconstructs measured pseudo-OCV curves using half-cell electrode potential curves to quantify three degradation mechanisms:
|
|
35
|
+
|
|
36
|
+
- **LLI**: Loss of lithium inventory (charge carrier loss)
|
|
37
|
+
- **LAM_an**: Loss of active material at anode
|
|
38
|
+
- **LAM_ca**: Loss of active material at cathode
|
|
39
|
+
|
|
40
|
+
The core algorithm reconstructs full-cell OCV as:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
OCV_cell(SOC) = U_cathode(α_ca · SOC + β_ca) - U_anode(α_an · SOC + β_an)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Where α scales capacity and β shifts the SOC window.
|
|
47
|
+
|
|
48
|
+
## ⚙️ Installation
|
|
49
|
+
|
|
50
|
+
PyPI release is coming soon:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# pip install pydma
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Install from source:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/tum-ees/pydma.git
|
|
60
|
+
cd pydma
|
|
61
|
+
pip install .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For development installation:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/tum-ees/pydma.git
|
|
68
|
+
cd pydma
|
|
69
|
+
pip install -e ".[dev,notebook]"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 🎮 Quick Start
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import pydma
|
|
76
|
+
from pydma import DMAAnalyzer, DMAConfig
|
|
77
|
+
|
|
78
|
+
# Load your electrode OCP data
|
|
79
|
+
anode_ocp = pydma.load_ocp("path/to/anode_ocp.csv")
|
|
80
|
+
cathode_ocp = pydma.load_ocp("path/to/cathode_ocp.csv")
|
|
81
|
+
|
|
82
|
+
# Create analyzer with configuration
|
|
83
|
+
config = DMAConfig(
|
|
84
|
+
direction="charge",
|
|
85
|
+
weight_ocv=100,
|
|
86
|
+
weight_dva=1,
|
|
87
|
+
weight_ica=0,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
analyzer = DMAAnalyzer(
|
|
91
|
+
anode_ocp=anode_ocp,
|
|
92
|
+
cathode_ocp=cathode_ocp,
|
|
93
|
+
config=config,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Run analysis on aging study data
|
|
97
|
+
results = analyzer.analyze_aging_study(
|
|
98
|
+
pocv_data={"CU1": pocv_cu1, "CU2": pocv_cu2, ...},
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Access degradation modes
|
|
102
|
+
print(f"LLI: {results.lam_results['CU2'].lli:.2%}")
|
|
103
|
+
print(f"LAM_an: {results.lam_results['CU2'].lam_anode:.2%}")
|
|
104
|
+
print(f"LAM_ca: {results.lam_results['CU2'].lam_cathode:.2%}")
|
|
105
|
+
|
|
106
|
+
# Plot results
|
|
107
|
+
results.plot_degradation_modes()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 📖 Key Features
|
|
111
|
+
|
|
112
|
+
### Blend Electrode Model
|
|
113
|
+
|
|
114
|
+
Supports blended electrodes (e.g., Silicon-Graphite anodes):
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
config = DMAConfig(
|
|
118
|
+
use_anode_blend=True,
|
|
119
|
+
gamma_anode_blend2_upper=0.30, # Max 30% silicon
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
analyzer = DMAAnalyzer(
|
|
123
|
+
anode_blend1_ocp=graphite_ocp, # Primary: Graphite
|
|
124
|
+
anode_blend2_ocp=silicon_ocp, # Secondary: Silicon
|
|
125
|
+
cathode_ocp=cathode_ocp,
|
|
126
|
+
config=config,
|
|
127
|
+
)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Inhomogeneity Modeling
|
|
131
|
+
|
|
132
|
+
Models electrode inhomogeneity effects:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
config = DMAConfig(
|
|
136
|
+
allow_anode_inhomogeneity=True,
|
|
137
|
+
allow_cathode_inhomogeneity=True,
|
|
138
|
+
max_inhomogeneity=0.3,
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Multiple Fitting Objectives
|
|
143
|
+
|
|
144
|
+
Combine OCV, DVA, and ICA fitting with custom weights:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
config = DMAConfig(
|
|
148
|
+
weight_ocv=100,
|
|
149
|
+
weight_dva=1,
|
|
150
|
+
weight_ica=0,
|
|
151
|
+
roi_dva_min=0.1,
|
|
152
|
+
roi_dva_max=0.9,
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Speed Presets
|
|
157
|
+
|
|
158
|
+
Choose optimization thoroughness:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
config = DMAConfig(speed_preset="thorough") # "fast", "medium", or "thorough"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 🔧 Silicon OCP Generation
|
|
165
|
+
|
|
166
|
+
Generate silicon OCP from measured blend electrode data:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from pydma.silicon import generate_silicon_curve
|
|
170
|
+
|
|
171
|
+
silicon_ocp = generate_silicon_curve(
|
|
172
|
+
blend_ocp=measured_blend_ocp,
|
|
173
|
+
graphite_ocp=graphite_reference,
|
|
174
|
+
gamma_si=0.245,
|
|
175
|
+
direction="lithiation",
|
|
176
|
+
)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## 📊 Parameter Vector Layout
|
|
180
|
+
|
|
181
|
+
The optimizer uses an 8-element parameter vector internally:
|
|
182
|
+
|
|
183
|
+
| Index | Parameter | Description |
|
|
184
|
+
|-------|-----------|-------------|
|
|
185
|
+
| 0 | α_an | Anode scaling / capacity ratio |
|
|
186
|
+
| 1 | β_an | Anode offset / SOC shift |
|
|
187
|
+
| 2 | α_ca | Cathode scaling |
|
|
188
|
+
| 3 | β_ca | Cathode offset |
|
|
189
|
+
| 4 | γ_blend2_an | Anode blend2 fraction (0 if disabled) |
|
|
190
|
+
| 5 | γ_blend2_ca | Cathode blend2 fraction (0 if disabled) |
|
|
191
|
+
| 6 | σ_an | Anode inhomogeneity magnitude |
|
|
192
|
+
| 7 | σ_ca | Cathode inhomogeneity magnitude |
|
|
193
|
+
|
|
194
|
+
## 📚 Documentation
|
|
195
|
+
|
|
196
|
+
See the [Getting Started Notebook](notebooks/getting_started.ipynb) for detailed examples.
|
|
197
|
+
|
|
198
|
+
## 🎖️ Acknowledgments
|
|
199
|
+
|
|
200
|
+
This is a Python translation of the [TUM-EES DegradationModeAnalysis](https://github.com/tum-ees/degradation-mode-analysis) MATLAB framework.
|
|
201
|
+
We would like to thank Johannes Natterer for providing the aging data set of a cyclic aged P45B cell and for help in translating into Python.
|
|
202
|
+
|
|
203
|
+
## 📯 Developers
|
|
204
|
+
|
|
205
|
+
- [Mathias Rehm](mailto:mathias.rehm@tum.de), Chair of Electrical Energy Storage Technology, School of Engineering and Design, Technical University of Munich, 80333 Munich, Germany
|
|
206
|
+
- [Josef Eizenhammer](mailto:josef.eizenhammer@tum.de), Chair of Electrical Energy Storage Technology, School of Engineering and Design, Technical University of Munich, 80333 Munich, Germany
|
|
207
|
+
- Moritz Günthner (student research project)
|
|
208
|
+
- Can Korkmaz (student research project)
|
|
209
|
+
|
|
210
|
+
## ✒️ Citation
|
|
211
|
+
|
|
212
|
+
This framework is the Python implementation of the MATLAB DegradationModeAnalysis toolbox.
|
|
213
|
+
If you use this repository in any publication, please cite:
|
|
214
|
+
|
|
215
|
+
> M. Rehm et al., "How to determine the degradation modes of lithium-ion batteries with silicon–graphite blend electrodes,"
|
|
216
|
+
> *Journal of Power Sources*, 2026, DOI: [10.1016/j.jpowsour.2026.239418](https://doi.org/10.1016/j.jpowsour.2026.239418)
|
|
217
|
+
|
|
218
|
+
The framework is also applied and validated on commercial sodium-ion batteries in the following publication.
|
|
219
|
+
We appreciate citing this work as well, and kindly ask you to do so if your work involves sodium-ion cells:
|
|
220
|
+
|
|
221
|
+
> M. Rehm et al., "Aging of commercial sodium-ion batteries with layered oxides: how to measure and analyze it?,"
|
|
222
|
+
> *EES Batteries*, 2026, DOI: [10.1039/D5EB00221D](https://doi.org/10.1039/D5EB00221D)
|
|
223
|
+
|
|
224
|
+
## 📜 License
|
|
225
|
+
|
|
226
|
+
BSD 3-Clause "New" or "Revised" License - see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pydma"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Battery Degradation Mode Analysis - Python implementation of TUM-EES DegradationModeAnalysis"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "BSD-3-Clause"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "TUM-EES", email = "mathias.rehm@tum.de"},
|
|
13
|
+
]
|
|
14
|
+
maintainers = [
|
|
15
|
+
{name = "TUM-EES", email = "mathias.rehm@tum.de"},
|
|
16
|
+
]
|
|
17
|
+
keywords = [
|
|
18
|
+
"battery",
|
|
19
|
+
"degradation",
|
|
20
|
+
"lithium-ion",
|
|
21
|
+
"sodium-ion",
|
|
22
|
+
"OCV",
|
|
23
|
+
"DVA",
|
|
24
|
+
"ICA",
|
|
25
|
+
"electrochemistry",
|
|
26
|
+
"aging",
|
|
27
|
+
]
|
|
28
|
+
classifiers = [
|
|
29
|
+
"Development Status :: 4 - Beta",
|
|
30
|
+
"Intended Audience :: Science/Research",
|
|
31
|
+
"Operating System :: OS Independent",
|
|
32
|
+
"Programming Language :: Python :: 3",
|
|
33
|
+
"Programming Language :: Python :: 3.9",
|
|
34
|
+
"Programming Language :: Python :: 3.10",
|
|
35
|
+
"Programming Language :: Python :: 3.11",
|
|
36
|
+
"Programming Language :: Python :: 3.12",
|
|
37
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
38
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
39
|
+
]
|
|
40
|
+
requires-python = ">=3.9"
|
|
41
|
+
dependencies = [
|
|
42
|
+
"numpy>=1.20.0",
|
|
43
|
+
"scipy>=1.7.0",
|
|
44
|
+
"pandas>=1.3.0",
|
|
45
|
+
"matplotlib>=3.4.0",
|
|
46
|
+
"statsmodels>=0.13.0",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[project.optional-dependencies]
|
|
50
|
+
dev = [
|
|
51
|
+
"pytest>=7.0.0",
|
|
52
|
+
"pytest-cov>=4.0.0",
|
|
53
|
+
"black>=23.0.0",
|
|
54
|
+
"isort>=5.12.0",
|
|
55
|
+
"pre-commit>=3.0.0",
|
|
56
|
+
"mypy>=1.0.0",
|
|
57
|
+
]
|
|
58
|
+
docs = [
|
|
59
|
+
"sphinx>=5.0.0",
|
|
60
|
+
"sphinx-rtd-theme>=1.0.0",
|
|
61
|
+
]
|
|
62
|
+
notebook = [
|
|
63
|
+
"jupyter>=1.0.0",
|
|
64
|
+
"ipywidgets>=8.0.0",
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[project.urls]
|
|
68
|
+
Homepage = "https://github.com/tum-ees/pydma"
|
|
69
|
+
Documentation = "https://github.com/tum-ees/pydma#readme"
|
|
70
|
+
Repository = "https://github.com/tum-ees/pydma.git"
|
|
71
|
+
Issues = "https://github.com/tum-ees/pydma/issues"
|
|
72
|
+
|
|
73
|
+
[tool.setuptools.packages.find]
|
|
74
|
+
where = ["src"]
|
|
75
|
+
|
|
76
|
+
[tool.setuptools.package-data]
|
|
77
|
+
"pydma.data.ocps" = ["*.csv"]
|
|
78
|
+
|
|
79
|
+
[tool.black]
|
|
80
|
+
line-length = 100
|
|
81
|
+
target-version = ["py39", "py310", "py311", "py312"]
|
|
82
|
+
|
|
83
|
+
[tool.isort]
|
|
84
|
+
profile = "black"
|
|
85
|
+
line_length = 100
|
|
86
|
+
|
|
87
|
+
[tool.mypy]
|
|
88
|
+
python_version = "3.9"
|
|
89
|
+
warn_return_any = true
|
|
90
|
+
warn_unused_configs = true
|
|
91
|
+
ignore_missing_imports = true
|
|
92
|
+
|
|
93
|
+
[tool.pytest.ini_options]
|
|
94
|
+
testpaths = ["tests"]
|
|
95
|
+
python_files = ["test_*.py"]
|
|
96
|
+
addopts = "-v --cov=pydma --cov-report=term-missing"
|
pydma-0.1.0/setup.cfg
ADDED