Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI

on:
push:
branches:
- main
pull_request:

jobs:
ruff:
uses: ./.github/workflows/ruff.yml

tests:
uses: ./.github/workflows/tests.yml

docs:
needs: [tests]
permissions:
contents: write
uses: ./.github/workflows/docs.yml
with:
deploy: ${{ github.event_name == 'push' }}
35 changes: 35 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Docs

on:
workflow_call:
inputs:
deploy:
description: "Push the built docs to gh-pages"
type: boolean
default: false

permissions:
contents: write

jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.11
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install ".[docs]"
- name: Build docs
run: mkdocs build

- name: Deploy docs
if: inputs.deploy
run: mkdocs gh-deploy --force
7 changes: 2 additions & 5 deletions .github/workflows/rull.yml → .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
name: Ruff

on:
push:
branches:
- main
pull_request:
workflow_call:

jobs:
ruff:
Expand All @@ -21,4 +18,4 @@ jobs:
run: ruff check .

- name: Ruff format check
run: ruff format . --check
run: ruff format . --check
7 changes: 2 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
name: Tests

on:
push:
branches:
- main
pull_request:
workflow_call:

jobs:
pytest:
test:
runs-on: ubuntu-latest

strategy:
Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Lukáš Adam

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
This repo contains Python code for automatic rotor design and optimization of synchronous reluctance machines (SynRMs).
The motivation is to improve the performance of SynRMs without using permanent magnets by optimizing the rotor flux barrier geometry. Candidate designs are generated in Python, simulated in Ansys Electronics Desktop, and optimized to increase the average torque and reduce torque ripple.

[Documentation](https://ai-rice.github.io/MachineDesign/)

<img src="figures/result.png" width="600">

Run "run.py" for random design evaluation and "run_optimization.py" for Bayesian optimization. Ansys Electronics Desktop and PyAEDT are required.
Expand Down
84 changes: 84 additions & 0 deletions docs/WINDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Winding layout

`machine_design/generic/winding.py` computes the phase and polarity layout of each slot, and assigns it to an AEDT model. It covers `compute_winding_layout` and `assign_slot_currents_to_aedt`.

## Basic usage

```python
compute_winding_layout(phases, slots, pole_pairs, coil_pitch=None, layers=1)
```

- phases, slots, pole_pairs: the machine's basic parameters.
- coil_pitch: coil span in slots.
- layers: 1 for a single layer winding (default), 2 for double layer.

**Example 1**, using the synrm_3f_36s motor (3 phases, 36 slots, 2 pole pairs, coil_pitch=9):

```python
from machine_design.generic.winding import compute_winding_layout

layout = compute_winding_layout(phases=3, slots=36, pole_pairs=2, coil_pitch=9, layers=1)
```

The first 9 slots of layout.phase and layout.polarity give:
```
phase[:9] = ['A','A','A','C','C','C','B','B','B']
polarity[:9] = [1, 1, 1, -1, -1, -1, 1, 1, 1]
```

**Summary:** Slots 0-2 carry phase A (positive), slots 3-5 carry phase C (negative), and slots 6-8 carry phase B (positive).

**Example 2**, using the synrm_5f_40s motor (5 phases, 40 slots, 2 pole pairs, coil_pitch=9):

```python
from machine_design.generic.winding import compute_winding_layout

layout = compute_winding_layout(phases=5, slots=40, pole_pairs=2, coil_pitch=9, layers=1)
```

The first 10 slots of layout.phase and layout.polarity give:
```
phase[:10] = ['A','D','D','B','B','E','E','C','C','A']
polarity[:10] = [1, -1, -1, 1, 1, -1, -1, 1, 1, -1]
```

**Summary:** Slot 0 carries phase A (positive), slots 1-2 carry phase D (negative), slots 3-4 carry phase B (positive), slots 5-6 carry phase E (negative), slots 7-8 carry phase C (positive), and slot 9 carries phase A (negative).

## Meaning of the outputs
compute_winding_layout returns a WindingLayout. For Example 1 above:

| Field | Value | Meaning |
|---|---|---|
| `coil_pitch` | `9` | Coil span in slots, including the automatically selected value if applicable. |
| `phase` | `['A','A','A','C',...]` | Phase letter of each slot's front coil side. |
| `polarity` | `[1,1,1,-1,...]` | Current direction of each slot's front coil side. |
| `phase_order` | `['A','B','C']` | The phase letters used in this winding. |
| `winding_factor` | `0.9598` | Pitch times distribution factor (0-1) (a warning is raised below 0.9). |
| `phase_angles` | `{'A':0.0,'B':-120.0,'C':-240.0}` | Electrical angle of each phase. |
| `p2_min_fem` | `1` | Minimum pole count for an FEM sector to close periodically (odd means the sector needs an antiperiodic boundary). |
| `phase_a_axis` | `120.0` | Electrical axis of phase A in the model (0-180 deg) (used to compute `InitPos`). |
| `phase_back` / `polarity_back` | `None` | Second (back) coil side per slot (only set for `layers=2`, `None` for a single layer). |


## Double layer windings (layers=2)
With layers=2, each slot holds two radially stacked coil slides: a front side, described by phase/polarity as before, and a back side, described by phase_back/polarity_back (same format, same slot order). The back side is the front side shifted by coil_pitch slots, with reversed polarity.

```python
layout = compute_winding_layout(phases=3, slots=36, pole_pairs=2, coil_pitch=9, layers=2)
```

The first 9 slots of layout.phase/layout.polarity (front) and layout.phase_back/layout.polarity_back (back):
```
phase[:9] = ['A','A','A','C','C','C','B','B','B']
phase_back[:9] = ['A','A','A','C','C','C','B','B','B']
polarity[:9] = [1, 1, 1, -1, -1, -1, 1, 1, 1]
polarity_back[:9] = [1, 1, 1, -1, -1, -1, 1, 1, 1]
```

Front and back happen to be identical here only because `coil_pitch=9` is a full pole pitch. A shorter pitch would make them differ.

To assign a double layer layout to AEDT, build both coil sides as separate named objects (one set per layer) and pass the second layer's object names as `coil_objects_back` to `assign_slot_currents_to_aedt`:

```python
assign_slot_currents_to_aedt(m2d, coil_objects, layout, phase_currents, coil_objects_back=coil_objects_back)
```
7 changes: 7 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
This website contains the documentation for the [MachineDesign](https://github.com/AI-RICE/MachineDesign) project.

The aim of the project is to provide a library for designing barriers in electrical machines, from geometry and winding generation to simulation and optimization. The core functionality includes:

- computing and assigning winding layouts for different phases, slots, and pole combinations, see [Winding layout](WINDING.md).
- building and simulating machine models through Ansys Electronics Desktop (AEDT).
- optimizing rotor barrier geometry and current setpoints with Bayesian optimization.
26 changes: 26 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
site_name: MachineDesign
repo_url: https://github.com/AI-RICE/MachineDesign
repo_name: MachineDesign

theme:
name: "material"
features:
- navigation.sections
- content.code.copy

markdown_extensions:
- attr_list
- admonition
- pymdownx.details
- pymdownx.superfences

plugins:
- markdown-exec
- mkdocstrings:
handlers:
python:
paths: [machine_design]

nav:
- Introduction: index.md
- Winding layout: WINDING.md
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ dependencies=[
dev = [
'pytest',
]
docs = [
"mkdocs>=1.6,<2.0",
"mkdocs-material>=9.0",
"mkdocstrings",
"mkdocstrings-python",
"markdown-exec",
]

[tool.setuptools]
packages = [
Expand Down
Loading