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.
Files changed (56) hide show
  1. motulator_gradnet-0.1.0/.github/workflows/docs.yml +54 -0
  2. motulator_gradnet-0.1.0/.github/workflows/motulator-main.yml +27 -0
  3. motulator_gradnet-0.1.0/.github/workflows/pre-commit.yml +17 -0
  4. motulator_gradnet-0.1.0/.github/workflows/publish.yml +53 -0
  5. motulator_gradnet-0.1.0/.github/workflows/tests.yml +26 -0
  6. motulator_gradnet-0.1.0/.gitignore +26 -0
  7. motulator_gradnet-0.1.0/.pre-commit-config.yaml +39 -0
  8. motulator_gradnet-0.1.0/LICENSE +21 -0
  9. motulator_gradnet-0.1.0/PKG-INFO +115 -0
  10. motulator_gradnet-0.1.0/README.md +77 -0
  11. motulator_gradnet-0.1.0/docs/Makefile +20 -0
  12. motulator_gradnet-0.1.0/docs/_templates/autoapi/index.rst +13 -0
  13. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/attribute.rst +1 -0
  14. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/class.rst +104 -0
  15. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/data.rst +38 -0
  16. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/exception.rst +1 -0
  17. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/function.rst +21 -0
  18. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/method.rst +21 -0
  19. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/module.rst +170 -0
  20. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/package.rst +1 -0
  21. motulator_gradnet-0.1.0/docs/_templates/autoapi/python/property.rst +20 -0
  22. motulator_gradnet-0.1.0/docs/make.bat +35 -0
  23. motulator_gradnet-0.1.0/docs/source/_static/css/custom.css +6 -0
  24. motulator_gradnet-0.1.0/docs/source/bibliography.md +4 -0
  25. motulator_gradnet-0.1.0/docs/source/conf.py +158 -0
  26. motulator_gradnet-0.1.0/docs/source/index.md +38 -0
  27. motulator_gradnet-0.1.0/docs/source/installation.md +53 -0
  28. motulator_gradnet-0.1.0/docs/source/refs.bib +15 -0
  29. motulator_gradnet-0.1.0/docs/source/usage.md +10 -0
  30. motulator_gradnet-0.1.0/examples/README.txt +4 -0
  31. motulator_gradnet-0.1.0/examples/datasets/baldor_fem.npz +0 -0
  32. motulator_gradnet-0.1.0/examples/datasets/baldor_meas.npz +0 -0
  33. motulator_gradnet-0.1.0/examples/datasets/brusa_meas.npz +0 -0
  34. motulator_gradnet-0.1.0/examples/plot_28kw_pmsyrm_curr_map_meas.py +107 -0
  35. motulator_gradnet-0.1.0/examples/plot_28kw_pmsyrm_flux_map_meas.py +108 -0
  36. motulator_gradnet-0.1.0/examples/plot_6kw_pmsyrm_curr_map_meas.py +105 -0
  37. motulator_gradnet-0.1.0/examples/plot_6kw_pmsyrm_flux_map_fem_harm.py +132 -0
  38. motulator_gradnet-0.1.0/examples/plot_6kw_pmsyrm_flux_map_meas.py +105 -0
  39. motulator_gradnet-0.1.0/examples/train_6kw_pmsyrm_curr_map_fem.py +75 -0
  40. motulator_gradnet-0.1.0/examples/train_6kw_pmsyrm_flux_map_fem_no_harm.py +74 -0
  41. motulator_gradnet-0.1.0/examples/trained_models/baldor_fem_curr_map_harm_softmax_d48_sub10.npz +0 -0
  42. motulator_gradnet-0.1.0/examples/trained_models/baldor_fem_flux_map_harm_pnorm_d48_sub10.npz +0 -0
  43. motulator_gradnet-0.1.0/examples/trained_models/baldor_fem_flux_map_pnorm_d12_sub20.npz +0 -0
  44. motulator_gradnet-0.1.0/examples/trained_models/baldor_meas_curr_map_squareplus_d12_sub10.npz +0 -0
  45. motulator_gradnet-0.1.0/examples/trained_models/baldor_meas_flux_map_pnorm_d6_sub10.npz +0 -0
  46. motulator_gradnet-0.1.0/examples/trained_models/brusa_meas_curr_map_squareplus_d12_sub100.npz +0 -0
  47. motulator_gradnet-0.1.0/examples/trained_models/brusa_meas_flux_map_pnorm_d12_sub100.npz +0 -0
  48. motulator_gradnet-0.1.0/motulator_gradnet/__init__.py +64 -0
  49. motulator_gradnet-0.1.0/motulator_gradnet/_dataset.py +203 -0
  50. motulator_gradnet-0.1.0/motulator_gradnet/_gn.py +247 -0
  51. motulator_gradnet-0.1.0/motulator_gradnet/_plot.py +612 -0
  52. motulator_gradnet-0.1.0/motulator_gradnet/_stats.py +92 -0
  53. motulator_gradnet-0.1.0/motulator_gradnet/_train.py +319 -0
  54. motulator_gradnet-0.1.0/pyproject.toml +91 -0
  55. motulator_gradnet-0.1.0/tests/test_gradnet.py +73 -0
  56. 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
+ [![PyPI version](https://img.shields.io/pypi/v/motulator-gradnet.svg)](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
+ [![PyPI version](https://img.shields.io/pypi/v/motulator-gradnet.svg)](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 %}