From 360376690c36ad677ceaf8e3a8042db35e20aefc Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Mon, 19 Oct 2026 15:00:52 +0200 Subject: [PATCH 01/18] a simple documentation with eaxmples of winding --- machine_design/generic/WINDING.md | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 machine_design/generic/WINDING.md diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md new file mode 100644 index 0000000..f6e8483 --- /dev/null +++ b/machine_design/generic/WINDING.md @@ -0,0 +1,77 @@ +# 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, uesing the synrm_3f_36s motor (3 phases, 36 slots, 2 pole pairs, coil_pitch=9): + +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[:12] = ['A','A','A','C','C','C','B','B','B'] +polarity[:12] = [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). + +Meaning of the outputs +compute_winding_layout returns a WindingLayout. For the example 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 phases present, in order. | +| `winding_factor` | `0.9598` | Pitch x 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/inner) 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 +(outer) side, described by phase/polarity as before, and a back (inner) +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`: + +assign_slot_currents_to_aedt(m2d, coil_objects, layout, phase_currents, coil_objects_back=coil_objects_back) + +Relation to coil_pitch/belt_offset + +The project's old winding code used belt_offset instead of coil_pitch. +Let pole_pitch_slots = slots/(2*pole_pairs) (the pole pitch in slots): +- If pole_pitch_slots is odd: coil_pitch = pole_pitch_slots, belt_offset = 0. +- If pole_pitch_slots is even: coil_pitch = pole_pitch_slots-1 with belt_offset=1, or +coil_pitch = pole_pitch_slots+1 with belt_offset=0. From d1cbf71e064fb65eb89b3c9fa3929b78891d6be0 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Mon, 19 Oct 2026 15:41:24 +0200 Subject: [PATCH 02/18] format adjust --- machine_design/generic/WINDING.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index f6e8483..3f248c3 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -8,25 +8,26 @@ It covers `compute_winding_layout` and `assign_slot_currents_to_aedt`. ```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, uesing the synrm_3f_36s motor (3 phases, 36 slots, 2 pole pairs, coil_pitch=9): +Example, using the synrm_3f_36s motor (3 phases, 36 slots, 2 pole pairs, coil_pitch=9): 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[:12] = ['A','A','A','C','C','C','B','B','B'] -polarity[:12] = [1, 1, 1, -1, -1, -1, 1, 1, 1] +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). -Meaning of the outputs +## Meaning of the outputs compute_winding_layout returns a WindingLayout. For the example above: | Field | Value | Meaning | @@ -42,7 +43,7 @@ compute_winding_layout returns a WindingLayout. For the example above: | `phase_back` / `polarity_back` | `None` | Second (back/inner) coil side per slot; only set for `layers=2`, `None` for a single layer. | -Double layer windings (layers=2) +## Double layer windings (layers=2) With layers=2, each slot holds two radially stacked coil slides: a front (outer) side, described by phase/polarity as before, and a back (inner) side, described by phase_back/polarity_back (same format, same slot order). @@ -51,6 +52,7 @@ 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): @@ -68,7 +70,7 @@ as `coil_objects_back` to `assign_slot_currents_to_aedt`: assign_slot_currents_to_aedt(m2d, coil_objects, layout, phase_currents, coil_objects_back=coil_objects_back) -Relation to coil_pitch/belt_offset +## Relation to coil_pitch/belt_offset The project's old winding code used belt_offset instead of coil_pitch. Let pole_pitch_slots = slots/(2*pole_pairs) (the pole pitch in slots): From 200bcd7facc54f52aa9e7439794a3a0c7df93e6e Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Wed, 21 Oct 2026 14:27:58 +0200 Subject: [PATCH 03/18] update format --- machine_design/generic/WINDING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index 3f248c3..b8e771f 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -16,12 +16,16 @@ compute_winding_layout(phases, slots, pole_pairs, coil_pitch=None, layers=1) Example, 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), From a8fa2f94f7c03131fe291020181198b1b91ab352 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Wed, 21 Oct 2026 14:39:03 +0200 Subject: [PATCH 04/18] adjust format --- machine_design/generic/WINDING.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index b8e771f..6d9c3f4 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -40,11 +40,11 @@ compute_winding_layout returns a WindingLayout. For the example above: | `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 phases present, in order. | -| `winding_factor` | `0.9598` | Pitch x distribution factor (0-1); a warning is raised below 0.9. | +| `winding_factor` | `0.9598` | Pitch x 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/inner) coil side per slot; only set for `layers=2`, `None` for a single layer. | +| `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/inner) coil side per slot (only set for `layers=2`, `None` for a single layer). | ## Double layer windings (layers=2) @@ -60,10 +60,12 @@ layout = compute_winding_layout(phases=3, slots=36, pole_pairs=2, coil_pitch=9, 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. From 96c127f6fc7359577996caee1d0e267089fa794e Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Wed, 21 Oct 2026 16:04:37 +0200 Subject: [PATCH 05/18] format adjust --- machine_design/generic/WINDING.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index 6d9c3f4..dcd10a7 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -39,20 +39,19 @@ compute_winding_layout returns a WindingLayout. For the example above: | `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 phases present, in order. | -| `winding_factor` | `0.9598` | Pitch x distribution factor (0-1) (a warning is raised below 0.9). | +| `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/inner) coil side per slot (only set for `layers=2`, `None` for a single layer). | +| `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 -(outer) side, described by phase/polarity as before, and a back (inner) -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. +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) From a8f46e1169f06b47d0b75a099f7375d3fddfebc6 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Wed, 21 Oct 2026 16:57:54 +0200 Subject: [PATCH 06/18] add example 2 (5f_40s) --- machine_design/generic/WINDING.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index dcd10a7..38d6972 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -14,7 +14,7 @@ compute_winding_layout(phases, slots, pole_pairs, coil_pitch=None, layers=1) - coil_pitch: coil span in slots. - layers: 1 for a single layer winding (default), 2 for double layer. -Example, using the synrm_3f_36s motor (3 phases, 36 slots, 2 pole pairs, coil_pitch=9): +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 @@ -31,8 +31,26 @@ 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 the example above: +compute_winding_layout returns a WindingLayout. For Example 1 above: | Field | Value | Meaning | |---|---|---| From 1f80aac24f7da6817d34b84fb1c77c1d3f9c7661 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Wed, 21 Oct 2026 17:01:46 +0200 Subject: [PATCH 07/18] bold "example" and "summary" --- machine_design/generic/WINDING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index 38d6972..1fce274 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -14,7 +14,7 @@ compute_winding_layout(phases, slots, pole_pairs, coil_pitch=None, layers=1) - 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): +**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 @@ -27,11 +27,11 @@ phase[:9] = ['A','A','A','C','C','C','B','B','B'] polarity[:9] = [1, 1, 1, -1, -1, -1, 1, 1, 1] ``` -Summary: +**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): +**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 @@ -44,7 +44,7 @@ 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: +**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). From 2bf573bf94cf9684f20d90647dbe53bc9f8df587 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 10:02:43 +0200 Subject: [PATCH 08/18] add coil_pitch --- machine_design/generic/WINDING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index 1fce274..39d2aa9 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -93,6 +93,22 @@ as `coil_objects_back` to `assign_slot_currents_to_aedt`: assign_slot_currents_to_aedt(m2d, coil_objects, layout, phase_currents, coil_objects_back=coil_objects_back) +## Automatically selecting coil_pitch + +When `coil_pitch` is `None`, it is chosen automatically as: +coil_pitch = round((2m-1)/(2m)*Q/(2p)) + +where `Q/(2p)` is the full pitch (phases=m, slots=Q, pole_pairs=p), and the ratio `(2m-1)/(2m)` is based on the suppression of higher harmonics. + +Since coil_pitch must be an integer, the program selects a value based on the number of layers: +- For layers = 1, the closest larger odd integer is chosen. +- For layers = 2, the value is rounded to the nearst integer. Both odd and even values are allowed. + +For example, with phases=3, slots=36, and pole_pairs=2, the calculated value is 7.5. +The program selects: +- layers = 1: coil_pitch=7 +- layers = 2: coil_pitch=8 + ## Relation to coil_pitch/belt_offset The project's old winding code used belt_offset instead of coil_pitch. From 1273f2fe3cb749db425391f2fb429684c4b956ad Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 11:37:37 +0200 Subject: [PATCH 09/18] delete Automatically selecting coil_pitch --- machine_design/generic/WINDING.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index 39d2aa9..1fce274 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -93,22 +93,6 @@ as `coil_objects_back` to `assign_slot_currents_to_aedt`: assign_slot_currents_to_aedt(m2d, coil_objects, layout, phase_currents, coil_objects_back=coil_objects_back) -## Automatically selecting coil_pitch - -When `coil_pitch` is `None`, it is chosen automatically as: -coil_pitch = round((2m-1)/(2m)*Q/(2p)) - -where `Q/(2p)` is the full pitch (phases=m, slots=Q, pole_pairs=p), and the ratio `(2m-1)/(2m)` is based on the suppression of higher harmonics. - -Since coil_pitch must be an integer, the program selects a value based on the number of layers: -- For layers = 1, the closest larger odd integer is chosen. -- For layers = 2, the value is rounded to the nearst integer. Both odd and even values are allowed. - -For example, with phases=3, slots=36, and pole_pairs=2, the calculated value is 7.5. -The program selects: -- layers = 1: coil_pitch=7 -- layers = 2: coil_pitch=8 - ## Relation to coil_pitch/belt_offset The project's old winding code used belt_offset instead of coil_pitch. From 41859b89727e774ff6b21dfac04bd2cfcd1c6612 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 11:43:55 +0200 Subject: [PATCH 10/18] ruff format --- machine_design/generic/WINDING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machine_design/generic/WINDING.md b/machine_design/generic/WINDING.md index 1fce274..fc9ca9f 100644 --- a/machine_design/generic/WINDING.md +++ b/machine_design/generic/WINDING.md @@ -18,6 +18,7 @@ compute_winding_layout(phases, slots, pole_pairs, coil_pitch=None, layers=1) ```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) ``` @@ -35,6 +36,7 @@ and slots 6-8 carry phase B (positive). ```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) ``` From 58c19f2f4d74dd6deebbc290462d43c576095deb Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 14:08:32 +0200 Subject: [PATCH 11/18] add docs (copied from Wildlife datasets) --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6e7ff08..cf77626 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 = [ From 2e21670523f1a8a2f7c5ac24f22a7c1ff83467fe Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 14:31:49 +0200 Subject: [PATCH 12/18] update according to wildlife datasets --- mkdocs.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 mkdocs.yml diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..b2b430a --- /dev/null +++ b/mkdocs.yml @@ -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 From 5dad29979653be2c8e944fcddcf0ca783c6fa117 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 14:52:07 +0200 Subject: [PATCH 13/18] add a index file according to wildlife datasets --- docs/index.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/index.md diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..7b8bd19 --- /dev/null +++ b/docs/index.md @@ -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. \ No newline at end of file From 8d4b6038a10ebb980b96155cc9cfc16b667f4a01 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 14:53:26 +0200 Subject: [PATCH 14/18] move WINDING.md to docs/ --- {machine_design/generic => docs}/WINDING.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {machine_design/generic => docs}/WINDING.md (100%) diff --git a/machine_design/generic/WINDING.md b/docs/WINDING.md similarity index 100% rename from machine_design/generic/WINDING.md rename to docs/WINDING.md From 86e05cc8edaa1dfb648e6fbe15cf27d00ed4c798 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 22 Oct 2026 15:47:47 +0200 Subject: [PATCH 15/18] unpdate workflows by using wildlife datasets as a template --- .github/workflows/ci.yml | 22 +++++++++++++++ .github/workflows/docs.yml | 35 ++++++++++++++++++++++++ .github/workflows/{rull.yml => ruff.yml} | 7 ++--- .github/workflows/tests.yml | 7 ++--- docs/WINDING.md | 2 ++ 5 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/docs.yml rename .github/workflows/{rull.yml => ruff.yml} (75%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0f7867f --- /dev/null +++ b/.github/workflows/ci.yml @@ -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' }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..65a7dcd --- /dev/null +++ b/.github/workflows/docs.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/rull.yml b/.github/workflows/ruff.yml similarity index 75% rename from .github/workflows/rull.yml rename to .github/workflows/ruff.yml index 3ea32a9..7f00e5e 100644 --- a/.github/workflows/rull.yml +++ b/.github/workflows/ruff.yml @@ -1,10 +1,7 @@ name: Ruff on: - push: - branches: - - main - pull_request: + workflow_call: jobs: ruff: @@ -21,4 +18,4 @@ jobs: run: ruff check . - name: Ruff format check - run: ruff format . --check \ No newline at end of file + run: ruff format . --check diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 607d8a4..2bb014c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,13 +1,10 @@ name: Tests on: - push: - branches: - - main - pull_request: + workflow_call: jobs: - pytest: + test: runs-on: ubuntu-latest strategy: diff --git a/docs/WINDING.md b/docs/WINDING.md index fc9ca9f..938fcd4 100644 --- a/docs/WINDING.md +++ b/docs/WINDING.md @@ -93,7 +93,9 @@ 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) +``` ## Relation to coil_pitch/belt_offset From 2528f005b05571ff3e8781b1830b4f229a540495 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Fri, 23 Oct 2026 08:31:58 +0200 Subject: [PATCH 16/18] Remove hard enters and original last paragraph --- docs/WINDING.md | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/docs/WINDING.md b/docs/WINDING.md index 938fcd4..7ac3ece 100644 --- a/docs/WINDING.md +++ b/docs/WINDING.md @@ -1,8 +1,6 @@ # 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`. +`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 @@ -28,9 +26,7 @@ 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). +**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): @@ -46,10 +42,7 @@ 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). +**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: @@ -68,17 +61,13 @@ compute_winding_layout returns a WindingLayout. For Example 1 above: ## 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. +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): +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'] @@ -86,21 +75,10 @@ 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. +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`: +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) ``` - -## Relation to coil_pitch/belt_offset - -The project's old winding code used belt_offset instead of coil_pitch. -Let pole_pitch_slots = slots/(2*pole_pairs) (the pole pitch in slots): -- If pole_pitch_slots is odd: coil_pitch = pole_pitch_slots, belt_offset = 0. -- If pole_pitch_slots is even: coil_pitch = pole_pitch_slots-1 with belt_offset=1, or -coil_pitch = pole_pitch_slots+1 with belt_offset=0. From 3e7e14046cb1edb6ccf92101616886bd88380262 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Fri, 23 Oct 2026 10:27:52 +0200 Subject: [PATCH 17/18] add MIT license file --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d943beb --- /dev/null +++ b/LICENSE @@ -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. \ No newline at end of file From fa48fd6e3282c2e5575aec2932f431a1c859041f Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Fri, 23 Oct 2026 10:28:34 +0200 Subject: [PATCH 18/18] add documentation link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 146c10d..f78a644 100644 --- a/README.md +++ b/README.md @@ -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/) + Run "run.py" for random design evaluation and "run_optimization.py" for Bayesian optimization. Ansys Electronics Desktop and PyAEDT are required.