motulator-gradnet 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.
- motulator_gradnet-0.1.0/.github/workflows/docs.yml +54 -0
- motulator_gradnet-0.1.0/.github/workflows/motulator-main.yml +27 -0
- motulator_gradnet-0.1.0/.github/workflows/pre-commit.yml +17 -0
- motulator_gradnet-0.1.0/.github/workflows/publish.yml +53 -0
- motulator_gradnet-0.1.0/.github/workflows/tests.yml +26 -0
- motulator_gradnet-0.1.0/.gitignore +26 -0
- motulator_gradnet-0.1.0/.pre-commit-config.yaml +39 -0
- motulator_gradnet-0.1.0/LICENSE +21 -0
- motulator_gradnet-0.1.0/PKG-INFO +115 -0
- motulator_gradnet-0.1.0/README.md +77 -0
- motulator_gradnet-0.1.0/docs/Makefile +20 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/index.rst +13 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/attribute.rst +1 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/class.rst +104 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/data.rst +38 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/exception.rst +1 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/function.rst +21 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/method.rst +21 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/module.rst +170 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/package.rst +1 -0
- motulator_gradnet-0.1.0/docs/_templates/autoapi/python/property.rst +20 -0
- motulator_gradnet-0.1.0/docs/make.bat +35 -0
- motulator_gradnet-0.1.0/docs/source/_static/css/custom.css +6 -0
- motulator_gradnet-0.1.0/docs/source/bibliography.md +4 -0
- motulator_gradnet-0.1.0/docs/source/conf.py +158 -0
- motulator_gradnet-0.1.0/docs/source/index.md +38 -0
- motulator_gradnet-0.1.0/docs/source/installation.md +53 -0
- motulator_gradnet-0.1.0/docs/source/refs.bib +15 -0
- motulator_gradnet-0.1.0/docs/source/usage.md +10 -0
- motulator_gradnet-0.1.0/examples/README.txt +4 -0
- motulator_gradnet-0.1.0/examples/datasets/baldor_fem.npz +0 -0
- motulator_gradnet-0.1.0/examples/datasets/baldor_meas.npz +0 -0
- motulator_gradnet-0.1.0/examples/datasets/brusa_meas.npz +0 -0
- motulator_gradnet-0.1.0/examples/plot_28kw_pmsyrm_curr_map_meas.py +107 -0
- motulator_gradnet-0.1.0/examples/plot_28kw_pmsyrm_flux_map_meas.py +108 -0
- motulator_gradnet-0.1.0/examples/plot_6kw_pmsyrm_curr_map_meas.py +105 -0
- motulator_gradnet-0.1.0/examples/plot_6kw_pmsyrm_flux_map_fem_harm.py +132 -0
- motulator_gradnet-0.1.0/examples/plot_6kw_pmsyrm_flux_map_meas.py +105 -0
- motulator_gradnet-0.1.0/examples/train_6kw_pmsyrm_curr_map_fem.py +75 -0
- motulator_gradnet-0.1.0/examples/train_6kw_pmsyrm_flux_map_fem_no_harm.py +74 -0
- motulator_gradnet-0.1.0/examples/trained_models/baldor_fem_curr_map_harm_softmax_d48_sub10.npz +0 -0
- motulator_gradnet-0.1.0/examples/trained_models/baldor_fem_flux_map_harm_pnorm_d48_sub10.npz +0 -0
- motulator_gradnet-0.1.0/examples/trained_models/baldor_fem_flux_map_pnorm_d12_sub20.npz +0 -0
- motulator_gradnet-0.1.0/examples/trained_models/baldor_meas_curr_map_squareplus_d12_sub10.npz +0 -0
- motulator_gradnet-0.1.0/examples/trained_models/baldor_meas_flux_map_pnorm_d6_sub10.npz +0 -0
- motulator_gradnet-0.1.0/examples/trained_models/brusa_meas_curr_map_squareplus_d12_sub100.npz +0 -0
- motulator_gradnet-0.1.0/examples/trained_models/brusa_meas_flux_map_pnorm_d12_sub100.npz +0 -0
- motulator_gradnet-0.1.0/motulator_gradnet/__init__.py +64 -0
- motulator_gradnet-0.1.0/motulator_gradnet/_dataset.py +203 -0
- motulator_gradnet-0.1.0/motulator_gradnet/_gn.py +247 -0
- motulator_gradnet-0.1.0/motulator_gradnet/_plot.py +612 -0
- motulator_gradnet-0.1.0/motulator_gradnet/_stats.py +92 -0
- motulator_gradnet-0.1.0/motulator_gradnet/_train.py +319 -0
- motulator_gradnet-0.1.0/pyproject.toml +91 -0
- motulator_gradnet-0.1.0/tests/test_gradnet.py +73 -0
- motulator_gradnet-0.1.0/tests/test_train.py +129 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
pages: write
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: docs-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
|
+
|
|
24
|
+
- name: Set up Python 3.12
|
|
25
|
+
uses: actions/setup-python@v7
|
|
26
|
+
with:
|
|
27
|
+
python-version: '3.12'
|
|
28
|
+
|
|
29
|
+
- name: Install PyTorch (CPU) and the package with the documentation dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch
|
|
33
|
+
pip install .[doc]
|
|
34
|
+
|
|
35
|
+
- name: Build Sphinx documentation
|
|
36
|
+
run: sphinx-build -b html docs/source docs/build/html
|
|
37
|
+
|
|
38
|
+
- name: Upload the documentation
|
|
39
|
+
uses: actions/upload-pages-artifact@v5
|
|
40
|
+
with:
|
|
41
|
+
path: docs/build/html
|
|
42
|
+
|
|
43
|
+
deploy:
|
|
44
|
+
# Pull requests only build the documentation
|
|
45
|
+
if: github.event_name != 'pull_request'
|
|
46
|
+
needs: build
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
environment:
|
|
49
|
+
name: github-pages
|
|
50
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
51
|
+
steps:
|
|
52
|
+
- name: Deploy to GitHub Pages
|
|
53
|
+
id: deployment
|
|
54
|
+
uses: actions/deploy-pages@v5
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Tests with motulator main
|
|
2
|
+
|
|
3
|
+
# Runs the tests weekly against the main branch of motulator, so that changes in
|
|
4
|
+
# motulator that break this package are noticed before they are released
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 4 * * 1'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- name: Set up Python 3.12
|
|
17
|
+
uses: actions/setup-python@v7
|
|
18
|
+
with:
|
|
19
|
+
python-version: '3.12'
|
|
20
|
+
- name: Install motulator from its main branch, PyTorch (CPU), and the package
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
pip install "motulator @ git+https://github.com/Aalto-Electric-Drives/motulator@main" pytest
|
|
24
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch
|
|
25
|
+
pip install --no-deps -e .
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: pytest
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Pre-commit
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pre-commit:
|
|
10
|
+
name: Run pre-commit
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout
|
|
14
|
+
uses: actions/checkout@v7
|
|
15
|
+
- uses: pre-commit/action@v3.0.1
|
|
16
|
+
with:
|
|
17
|
+
extra_args: --all-files
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Builds the package and publishes it to PyPI when a release is published on GitHub.
|
|
4
|
+
# The package is uploaded with the repository secret PYPI_API_TOKEN until a trusted
|
|
5
|
+
# publisher for this workflow is added on PyPI; then the password line is removed.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
|
+
with:
|
|
20
|
+
persist-credentials: false
|
|
21
|
+
- name: Set up Python 3.12
|
|
22
|
+
uses: actions/setup-python@v7
|
|
23
|
+
with:
|
|
24
|
+
python-version: '3.12'
|
|
25
|
+
- name: Build the wheel and the source distribution
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install build
|
|
29
|
+
python -m build
|
|
30
|
+
- name: Store the distributions
|
|
31
|
+
uses: actions/upload-artifact@v7
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
publish:
|
|
37
|
+
needs: build
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
environment:
|
|
40
|
+
name: pypi
|
|
41
|
+
url: https://pypi.org/p/motulator-gradnet
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write # Needed for trusted publishing
|
|
44
|
+
steps:
|
|
45
|
+
- name: Download the distributions
|
|
46
|
+
uses: actions/download-artifact@v8
|
|
47
|
+
with:
|
|
48
|
+
name: dist
|
|
49
|
+
path: dist/
|
|
50
|
+
- name: Publish to PyPI
|
|
51
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
52
|
+
with:
|
|
53
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ['3.12', '3.13', '3.14']
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
17
|
+
uses: actions/setup-python@v7
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- name: Install PyTorch (CPU) and the package with the latest motulator
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch
|
|
24
|
+
pip install -e .[dev]
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: pytest
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Byte-compiled files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
|
|
5
|
+
# Distribution
|
|
6
|
+
*.egg-info/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# macOS specific
|
|
13
|
+
.DS_Store
|
|
14
|
+
|
|
15
|
+
# Sphinx documentation
|
|
16
|
+
docs/build/
|
|
17
|
+
docs/source/autoapi/
|
|
18
|
+
docs/source/examples/
|
|
19
|
+
docs/source/sg_execution_times.rst
|
|
20
|
+
|
|
21
|
+
# Caches
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
|
|
25
|
+
# Model trained by the usage example of the README
|
|
26
|
+
/flux_map.npz
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
|
|
3
|
+
# Generic
|
|
4
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
5
|
+
rev: v6.0.0
|
|
6
|
+
hooks:
|
|
7
|
+
- id: end-of-file-fixer
|
|
8
|
+
- id: trailing-whitespace
|
|
9
|
+
- id: check-toml
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
|
|
12
|
+
# Ruff formatter & linter
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.17.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: ruff
|
|
17
|
+
args: [--fix]
|
|
18
|
+
name: ruff (linter)
|
|
19
|
+
- id: ruff-format
|
|
20
|
+
name: ruff (formatter)
|
|
21
|
+
|
|
22
|
+
# Pyright
|
|
23
|
+
- repo: https://github.com/RobertCraigie/pyright-python
|
|
24
|
+
rev: v1.1.414
|
|
25
|
+
hooks:
|
|
26
|
+
- id: pyright
|
|
27
|
+
additional_dependencies: ["motulator>=0.15,<0.17", numpy, matplotlib, torch, tqdm, pytest, sphinx-gallery]
|
|
28
|
+
args:
|
|
29
|
+
- --venvpath=./.venv
|
|
30
|
+
|
|
31
|
+
# MyST Markdown formatter
|
|
32
|
+
- repo: https://github.com/executablebooks/mdformat
|
|
33
|
+
rev: 1.0.0
|
|
34
|
+
hooks:
|
|
35
|
+
- id: mdformat
|
|
36
|
+
name: mdformat (MyST)
|
|
37
|
+
additional_dependencies:
|
|
38
|
+
- mdformat-myst
|
|
39
|
+
types_or: [markdown]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aalto Electric Drives
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: motulator-gradnet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Training of gradient-network magnetic models of synchronous machines for motulator
|
|
5
|
+
Project-URL: Homepage, https://github.com/Aalto-Electric-Drives/motulator-gradnet
|
|
6
|
+
Project-URL: Documentation, https://aalto-electric-drives.github.io/motulator-gradnet/
|
|
7
|
+
Author-email: Marko Hinkkanen <marko.hinkkanen@aalto.fi>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: flux map,gradient network,machine learning,magnetic model,motor,neural network,saturation,simulation,synchronous machine
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Requires-Dist: matplotlib
|
|
19
|
+
Requires-Dist: motulator<0.17,>=0.15.0
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: torch
|
|
22
|
+
Requires-Dist: tqdm
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
25
|
+
Requires-Dist: pyright; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
28
|
+
Provides-Extra: doc
|
|
29
|
+
Requires-Dist: myst-parser; extra == 'doc'
|
|
30
|
+
Requires-Dist: numpydoc; extra == 'doc'
|
|
31
|
+
Requires-Dist: sphinx; extra == 'doc'
|
|
32
|
+
Requires-Dist: sphinx-autoapi; extra == 'doc'
|
|
33
|
+
Requires-Dist: sphinx-book-theme; extra == 'doc'
|
|
34
|
+
Requires-Dist: sphinx-copybutton; extra == 'doc'
|
|
35
|
+
Requires-Dist: sphinx-gallery; extra == 'doc'
|
|
36
|
+
Requires-Dist: sphinxcontrib-bibtex; extra == 'doc'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# motulator-gradnet
|
|
40
|
+
|
|
41
|
+
**Training of gradient-network magnetic models of synchronous machines for [motulator](https://github.com/Aalto-Electric-Drives/motulator)**
|
|
42
|
+
|
|
43
|
+
[](https://pypi.org/project/motulator-gradnet/)
|
|
44
|
+
|
|
45
|
+
Documentation: https://aalto-electric-drives.github.io/motulator-gradnet/
|
|
46
|
+
|
|
47
|
+
This package trains gradient networks (GradNets) that model the current and flux linkage maps of synchronous machines, including spatial harmonics, from measured or finite-element data [1]. A GradNet is the gradient of a scalar state function, the magnetic energy or co-energy, so the map is a conservative vector field by construction [2], and the monotonicity of the flux-linkage–current map is ensured. The networks are defined and trained with PyTorch. A trained network is saved as a NumPy function, which the magnetic maps of *motulator* evaluate in the machine models and control systems without PyTorch. The package also compares the trained maps with the data.
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
Install the package from PyPI (*motulator* and PyTorch are installed as dependencies):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install motulator-gradnet
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The PyTorch wheels on PyPI for Linux include CUDA support and are large. The small networks of this package are trained in a reasonable time on a CPU, so a CPU-only build is sufficient. It is installed before the package with the command:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The package supports *motulator* 0.15 and 0.16, and the support is extended after each new release of *motulator* has been tested. For development, clone the repository and install the package with `pip install -e .[dev]`.
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
A dataset is an npz file with the complex arrays `i_s_dq` (stator current, A) and `psi_s_dq` (stator flux linkage, Vs) of the same shape, peak-valued space vectors in rotor coordinates. A dataset with spatial harmonics has also the arrays `theta_m` (electrical rotor angle, rad) and `tau_m` (electromagnetic torque per pole pair, Nm). The following example trains a flux linkage map from the measured dataset of a 5.6-kW PM synchronous reluctance machine in `examples/datasets/`:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import motulator.drive.gradnet as gn
|
|
71
|
+
from motulator.drive import utils
|
|
72
|
+
|
|
73
|
+
from motulator_gradnet import (
|
|
74
|
+
PNormGradient,
|
|
75
|
+
get_training_data,
|
|
76
|
+
print_flux_map_errors_meas,
|
|
77
|
+
train_gradnet,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Base values of the machine, used to normalize the data
|
|
81
|
+
nom = utils.NominalValues(U=460, I=8.8, f=60, P=5.6e3, tau=29.7)
|
|
82
|
+
base = utils.BaseValues.from_nominal(nom, n_p=2)
|
|
83
|
+
|
|
84
|
+
# Train a flux map from every 10th data point and save it
|
|
85
|
+
dataset_path = "examples/datasets/baldor_meas.npz"
|
|
86
|
+
train_gradnet(
|
|
87
|
+
dataset_path,
|
|
88
|
+
base,
|
|
89
|
+
is_flux_map=True,
|
|
90
|
+
embed_dim=6,
|
|
91
|
+
epochs=20000,
|
|
92
|
+
subsample=10,
|
|
93
|
+
activation=PNormGradient,
|
|
94
|
+
save_model_path="flux_map.npz",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# The trained map is evaluated with motulator, without PyTorch
|
|
98
|
+
flux_map = gn.FluxMap(gn.load_gradnet("flux_map.npz"))
|
|
99
|
+
print(flux_map(5 + 8j)) # Flux linkage (Vs) at the current (A)
|
|
100
|
+
|
|
101
|
+
# Compare with the data points not used in the training
|
|
102
|
+
_, val_data = get_training_data(dataset_path, base, subsample=10)
|
|
103
|
+
print_flux_map_errors_meas(flux_map, val_data, base)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The map is used in the machine models and control systems of *motulator* through its parameter classes, e.g., `SaturatedSynchronousMachinePars(n_p=2, R_s=0.63, psi_s_dq_fcn=flux_map)`. Complete examples, which also train current maps and maps with spatial harmonics, are in the [example gallery](https://aalto-electric-drives.github.io/motulator-gradnet/examples/index.html), and simulation examples using the trained maps are in the [documentation of *motulator*](https://aalto-electric-drives.github.io/motulator/drive_examples/index.html).
|
|
107
|
+
|
|
108
|
+
## References
|
|
109
|
+
|
|
110
|
+
1. Li, Foissner, Martin, Piippo, Hinkkanen, "Gradient networks for universal magnetic modeling of synchronous machines," 2026, https://arxiv.org/abs/2602.14947
|
|
111
|
+
1. Chaudhari, Pranav, Moura, "Gradient networks," IEEE Trans. Signal Process., 2025, https://doi.org/10.1109/TSP.2024.3496692
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# motulator-gradnet
|
|
2
|
+
|
|
3
|
+
**Training of gradient-network magnetic models of synchronous machines for [motulator](https://github.com/Aalto-Electric-Drives/motulator)**
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/motulator-gradnet/)
|
|
6
|
+
|
|
7
|
+
Documentation: https://aalto-electric-drives.github.io/motulator-gradnet/
|
|
8
|
+
|
|
9
|
+
This package trains gradient networks (GradNets) that model the current and flux linkage maps of synchronous machines, including spatial harmonics, from measured or finite-element data [1]. A GradNet is the gradient of a scalar state function, the magnetic energy or co-energy, so the map is a conservative vector field by construction [2], and the monotonicity of the flux-linkage–current map is ensured. The networks are defined and trained with PyTorch. A trained network is saved as a NumPy function, which the magnetic maps of *motulator* evaluate in the machine models and control systems without PyTorch. The package also compares the trained maps with the data.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Install the package from PyPI (*motulator* and PyTorch are installed as dependencies):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install motulator-gradnet
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The PyTorch wheels on PyPI for Linux include CUDA support and are large. The small networks of this package are trained in a reasonable time on a CPU, so a CPU-only build is sufficient. It is installed before the package with the command:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install --index-url https://download.pytorch.org/whl/cpu torch
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The package supports *motulator* 0.15 and 0.16, and the support is extended after each new release of *motulator* has been tested. For development, clone the repository and install the package with `pip install -e .[dev]`.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
A dataset is an npz file with the complex arrays `i_s_dq` (stator current, A) and `psi_s_dq` (stator flux linkage, Vs) of the same shape, peak-valued space vectors in rotor coordinates. A dataset with spatial harmonics has also the arrays `theta_m` (electrical rotor angle, rad) and `tau_m` (electromagnetic torque per pole pair, Nm). The following example trains a flux linkage map from the measured dataset of a 5.6-kW PM synchronous reluctance machine in `examples/datasets/`:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import motulator.drive.gradnet as gn
|
|
33
|
+
from motulator.drive import utils
|
|
34
|
+
|
|
35
|
+
from motulator_gradnet import (
|
|
36
|
+
PNormGradient,
|
|
37
|
+
get_training_data,
|
|
38
|
+
print_flux_map_errors_meas,
|
|
39
|
+
train_gradnet,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Base values of the machine, used to normalize the data
|
|
43
|
+
nom = utils.NominalValues(U=460, I=8.8, f=60, P=5.6e3, tau=29.7)
|
|
44
|
+
base = utils.BaseValues.from_nominal(nom, n_p=2)
|
|
45
|
+
|
|
46
|
+
# Train a flux map from every 10th data point and save it
|
|
47
|
+
dataset_path = "examples/datasets/baldor_meas.npz"
|
|
48
|
+
train_gradnet(
|
|
49
|
+
dataset_path,
|
|
50
|
+
base,
|
|
51
|
+
is_flux_map=True,
|
|
52
|
+
embed_dim=6,
|
|
53
|
+
epochs=20000,
|
|
54
|
+
subsample=10,
|
|
55
|
+
activation=PNormGradient,
|
|
56
|
+
save_model_path="flux_map.npz",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# The trained map is evaluated with motulator, without PyTorch
|
|
60
|
+
flux_map = gn.FluxMap(gn.load_gradnet("flux_map.npz"))
|
|
61
|
+
print(flux_map(5 + 8j)) # Flux linkage (Vs) at the current (A)
|
|
62
|
+
|
|
63
|
+
# Compare with the data points not used in the training
|
|
64
|
+
_, val_data = get_training_data(dataset_path, base, subsample=10)
|
|
65
|
+
print_flux_map_errors_meas(flux_map, val_data, base)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The map is used in the machine models and control systems of *motulator* through its parameter classes, e.g., `SaturatedSynchronousMachinePars(n_p=2, R_s=0.63, psi_s_dq_fcn=flux_map)`. Complete examples, which also train current maps and maps with spatial harmonics, are in the [example gallery](https://aalto-electric-drives.github.io/motulator-gradnet/examples/index.html), and simulation examples using the trained maps are in the [documentation of *motulator*](https://aalto-electric-drives.github.io/motulator/drive_examples/index.html).
|
|
69
|
+
|
|
70
|
+
## References
|
|
71
|
+
|
|
72
|
+
1. Li, Foissner, Martin, Piippo, Hinkkanen, "Gradient networks for universal magnetic modeling of synchronous machines," 2026, https://arxiv.org/abs/2602.14947
|
|
73
|
+
1. Chaudhari, Pranav, Moura, "Gradient networks," IEEE Trans. Signal Process., 2025, https://doi.org/10.1109/TSP.2024.3496692
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= sphinx-build
|
|
8
|
+
SOURCEDIR = source
|
|
9
|
+
BUILDDIR = build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
18
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
19
|
+
%: Makefile
|
|
20
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
API Reference
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
This page contains auto-generated API reference documentation [#f1]_.
|
|
5
|
+
|
|
6
|
+
.. toctree::
|
|
7
|
+
:titlesonly:
|
|
8
|
+
|
|
9
|
+
{% for page in pages|selectattr("is_top_level_object") %}
|
|
10
|
+
{{ page.include_path }}
|
|
11
|
+
{% endfor %}
|
|
12
|
+
|
|
13
|
+
.. [#f1] Created with `sphinx-autoapi <https://github.com/readthedocs/sphinx-autoapi>`_
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{% extends "python/data.rst" %}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{% if obj.display %}
|
|
2
|
+
{% if is_own_page %}
|
|
3
|
+
{{ obj.id }}
|
|
4
|
+
{{ "=" * obj.id | length }}
|
|
5
|
+
|
|
6
|
+
{% endif %}
|
|
7
|
+
{% set visible_children = obj.children|selectattr("display")|list %}
|
|
8
|
+
{% set own_page_children = visible_children|selectattr("type", "in", own_page_types)|list %}
|
|
9
|
+
{% if is_own_page and own_page_children %}
|
|
10
|
+
.. toctree::
|
|
11
|
+
:hidden:
|
|
12
|
+
|
|
13
|
+
{% for child in own_page_children %}
|
|
14
|
+
{{ child.include_path }}
|
|
15
|
+
{% endfor %}
|
|
16
|
+
|
|
17
|
+
{% endif %}
|
|
18
|
+
.. py:{{ obj.type }}:: {% if is_own_page %}{{ obj.id }}{% else %}{{ obj.short_name }}{% endif %}{% if obj.args %}({{ obj.args }}){% endif %}
|
|
19
|
+
|
|
20
|
+
{% for (args, return_annotation) in obj.overloads %}
|
|
21
|
+
{{ " " * (obj.type | length) }} {{ obj.short_name }}{% if args %}({{ args }}){% endif %}
|
|
22
|
+
|
|
23
|
+
{% endfor %}
|
|
24
|
+
{% if obj.bases %}
|
|
25
|
+
{% if "show-inheritance" in autoapi_options %}
|
|
26
|
+
|
|
27
|
+
Bases: {% for base in obj.bases %}{{ base|link_objs }}{% if not loop.last %}, {% endif %}{% endfor %}
|
|
28
|
+
{% endif %}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
{% if "show-inheritance-diagram" in autoapi_options and obj.bases != ["object"] %}
|
|
32
|
+
.. autoapi-inheritance-diagram:: {{ obj.obj["full_name"] }}
|
|
33
|
+
:parts: 1
|
|
34
|
+
{% if "private-members" in autoapi_options %}
|
|
35
|
+
:private-bases:
|
|
36
|
+
{% endif %}
|
|
37
|
+
|
|
38
|
+
{% endif %}
|
|
39
|
+
{% endif %}
|
|
40
|
+
{% if obj.docstring %}
|
|
41
|
+
|
|
42
|
+
{{ obj.docstring|indent(3) }}
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% for obj_item in visible_children %}
|
|
45
|
+
{% if obj_item.type not in own_page_types %}
|
|
46
|
+
|
|
47
|
+
{{ obj_item.render()|indent(3) }}
|
|
48
|
+
{% endif %}
|
|
49
|
+
{% endfor %}
|
|
50
|
+
{% if is_own_page and own_page_children %}
|
|
51
|
+
{% set visible_attributes = own_page_children|selectattr("type", "equalto", "attribute")|list %}
|
|
52
|
+
{% if visible_attributes %}
|
|
53
|
+
Attributes
|
|
54
|
+
----------
|
|
55
|
+
|
|
56
|
+
.. autoapisummary::
|
|
57
|
+
|
|
58
|
+
{% for attribute in visible_attributes %}
|
|
59
|
+
{{ attribute.id }}
|
|
60
|
+
{% endfor %}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
{% endif %}
|
|
64
|
+
{% set visible_exceptions = own_page_children|selectattr("type", "equalto", "exception")|list %}
|
|
65
|
+
{% if visible_exceptions %}
|
|
66
|
+
Exceptions
|
|
67
|
+
----------
|
|
68
|
+
|
|
69
|
+
.. autoapisummary::
|
|
70
|
+
|
|
71
|
+
{% for exception in visible_exceptions %}
|
|
72
|
+
{{ exception.id }}
|
|
73
|
+
{% endfor %}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
{% endif %}
|
|
77
|
+
{% set visible_classes = own_page_children|selectattr("type", "equalto", "class")|list %}
|
|
78
|
+
{% if visible_classes %}
|
|
79
|
+
Classes
|
|
80
|
+
-------
|
|
81
|
+
|
|
82
|
+
.. autoapisummary::
|
|
83
|
+
|
|
84
|
+
{% for klass in visible_classes %}
|
|
85
|
+
{{ klass.id }}
|
|
86
|
+
{% endfor %}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
{% endif %}
|
|
90
|
+
{% set visible_methods = own_page_children|selectattr("type", "equalto", "method")|list %}
|
|
91
|
+
{% if visible_methods %}
|
|
92
|
+
Methods
|
|
93
|
+
-------
|
|
94
|
+
|
|
95
|
+
.. autoapisummary::
|
|
96
|
+
|
|
97
|
+
{% for method in visible_methods %}
|
|
98
|
+
{{ method.id }}
|
|
99
|
+
{% endfor %}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
{% endif %}
|
|
103
|
+
{% endif %}
|
|
104
|
+
{% endif %}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{% if obj.display %}
|
|
2
|
+
{% if is_own_page %}
|
|
3
|
+
{{ obj.id }}
|
|
4
|
+
{{ "=" * obj.id | length }}
|
|
5
|
+
|
|
6
|
+
{% endif %}
|
|
7
|
+
.. py:{{ obj.type }}:: {% if is_own_page %}{{ obj.id }}{% else %}{{ obj.name }}{% endif %}
|
|
8
|
+
{% if obj.annotation is not none %}
|
|
9
|
+
|
|
10
|
+
:type: {% if obj.annotation %} {{ obj.annotation }}{% endif %}
|
|
11
|
+
{% endif %}
|
|
12
|
+
{% if obj.value is not none %}
|
|
13
|
+
|
|
14
|
+
{% if obj.value.splitlines()|count > 1 %}
|
|
15
|
+
:value: Multiline-String
|
|
16
|
+
|
|
17
|
+
.. raw:: html
|
|
18
|
+
|
|
19
|
+
<details><summary>Show Value</summary>
|
|
20
|
+
|
|
21
|
+
.. code-block:: python
|
|
22
|
+
|
|
23
|
+
{{ obj.value|indent(width=6,blank=true) }}
|
|
24
|
+
|
|
25
|
+
.. raw:: html
|
|
26
|
+
|
|
27
|
+
</details>
|
|
28
|
+
|
|
29
|
+
{% else %}
|
|
30
|
+
:value: {{ obj.value|truncate(100) }}
|
|
31
|
+
{% endif %}
|
|
32
|
+
{% endif %}
|
|
33
|
+
|
|
34
|
+
{% if obj.docstring %}
|
|
35
|
+
|
|
36
|
+
{{ obj.docstring|indent(3) }}
|
|
37
|
+
{% endif %}
|
|
38
|
+
{% endif %}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{% extends "python/class.rst" %}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{% if obj.display %}
|
|
2
|
+
{% if is_own_page %}
|
|
3
|
+
{{ obj.id }}
|
|
4
|
+
{{ "=" * obj.id | length }}
|
|
5
|
+
|
|
6
|
+
{% endif %}
|
|
7
|
+
.. py:function:: {% if is_own_page %}{{ obj.id }}{% else %}{{ obj.short_name }}{% endif %}({{ obj.args }}){% if obj.return_annotation is not none %} -> {{ obj.return_annotation }}{% endif %}
|
|
8
|
+
{% for (args, return_annotation) in obj.overloads %}
|
|
9
|
+
|
|
10
|
+
{%+ if is_own_page %}{{ obj.id }}{% else %}{{ obj.short_name }}{% endif %}({{ args }}){% if return_annotation is not none %} -> {{ return_annotation }}{% endif %}
|
|
11
|
+
{% endfor %}
|
|
12
|
+
{% for property in obj.properties %}
|
|
13
|
+
|
|
14
|
+
:{{ property }}:
|
|
15
|
+
{% endfor %}
|
|
16
|
+
|
|
17
|
+
{% if obj.docstring %}
|
|
18
|
+
|
|
19
|
+
{{ obj.docstring|indent(3) }}
|
|
20
|
+
{% endif %}
|
|
21
|
+
{% endif %}
|