From 917b988eb95d44e8e6031a44504d93319362833d Mon Sep 17 00:00:00 2001 From: sadda Date: Mon, 13 Jul 2026 11:38:04 +0000 Subject: [PATCH 1/3] Added contributing --- CONTRIBUTING.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3c9f0f4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,68 @@ +# Contributing to MachineDesign + +A short, shared "culture" so several people can do their own research on this repo without stepping on each other. It exists because we hit the failure mode it prevents: the *same* fix (the AEDT `ddt()` output-var bug) was written independently on three branches, and the core machine model `machine_design/design2.py` has drifted into a different version on every branch. The rules below keep shared code shared and personal work personal. + +## The one rule + +> **Shared code lives on `main` and is changed only by a small PR to `main`. +> Your research branch adds and edits only `experiments//`.** + +If you find yourself editing `machine_design/` or `optimization/` on your own branch, stop — that's a change everyone needs, so it's a PR to `main`. Then rebase your branch on `main` and everyone gets the fix once. + +## Three layers — what goes where + +| layer | directory | shared? | contains | +|---|---|---|---| +| **Designs** | `machine_design/` | yes (main) | *anchor* machines, geometry generators, and the one-solve FEA evaluation | +| **Methods** | `optimization/` | yes (main) | design-**agnostic** optimizers (BO, Thompson, nested, PFN…) that talk to designs only through the interface | +| **Experiments** | `experiments//` | no (your branch) | your run configs, the profile/objective you're studying, analysis notebooks, result artifacts, write-ups | + +The point of the split: **a method should run on any design, and a design should be optimizable by any method.** Neither should import the other's internals — they meet at the interface (below). + +## Anchor designs — named, frozen, *derived not forked* + +An **anchor** is a named, version-controlled machine definition — everything needed to instantiate and solve one physical machine: + +``` +class, slots, phases, winding (turns, Rs), end-winding Lew, rotor radii, +geometry generator + parameter bounds, FEA template +``` + +Anchors live in `machine_design/anchors.py` (or `anchors/.yaml`) and are named `_f_s_t`, e.g. `synrm_5f_60s_113t` (the 500 W 5-phase machine). Rules: + +- **Derive, don't fork.** To study a variant (add magnets, change turns), *reference* an anchor and override only what differs — do **not** edit the anchor's class in place. A genuinely new machine is a **new anchor**, appended to the registry. +- **Anchors are append-only and shared.** A bug in an anchor's FEA (like the `ddt()` one) is fixed **once**, by a PR to `main`; everyone rebases and inherits it. No per-branch copies of `design2.py`. + +## Methods and the design interface + +An optimizer in `optimization/` depends only on this contract, which every anchor implements: + +```python +sample_feasible_geometry() -> g # a valid rotor (normalized params) +geometry_bounds() -> (lb, ub) +evaluate(g, currents) -> dict # ONE FEA solve -> {T, ripple, flux, ...} +peak_current(currents) -> float # analytic constraints, no FEA +``` + +So `optimization/pathwise_thompson.py` never imports a specific design; you point it at `anchors.get("synrm_5f_60s_113t")` (or any other) and it runs. If you write a new method, put it here and it's instantly reusable by everyone. If you need a response the interface doesn't expose, extend the **interface** (a PR to main), not your method. + +## Branch & merge workflow + +- **`main` is the living trunk**, not a stale base. Keep it green; rebase onto it often. +- **Research branches are thin.** Name them `exp/` or `/` (e.g. `exp/reluctance-5f`, `vs/pfn-revisited`). They should almost never show a diff outside `experiments//`. +- **Shared-code change → PR to `main`.** Small, focused, reviewed by one other person. This is the whole discipline; everything else follows from it. +- Don't let a branch live for months without merging its shared parts back — that is how we got four divergent `design2.py`s. + +## Running things + +All compute goes through the SLURM queue on `bayes` — see [`bayes-queue/README.md`](bayes-queue/README.md). One FEA solve = 1 core + its own `--mem` + one license; submit sweeps as job arrays (`bayes-queue/sweep.sbatch`). + +## Quick checklists + +**I want to optimize an existing machine with an existing method** → in `experiments//`, write a config that picks an anchor + a method + your objective/constraints, and an sbatch to run it. Touch nothing shared. + +**I want to study a new machine** → add an **anchor** (PR to `main`); if it's a variant, derive it from an existing anchor. Then use it from your experiment. + +**I want a new optimization method** → add it to `optimization/` against the interface (PR to `main`). Now anyone can use it on any anchor. + +**I found a bug in a shared design/method** → fix it on `main` via PR, then rebase your branch. Do not patch it only on your branch. From 156fb32067375b1a2cf6291ea586d69fda75d6fd Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 3 Sep 2026 11:07:33 +0200 Subject: [PATCH 2/3] Update CONTRIBUTING.md to reflect current structure and PR workflow --- CONTRIBUTING.md | 80 +++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 49 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c9f0f4..44b0b9b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,68 +1,50 @@ # Contributing to MachineDesign -A short, shared "culture" so several people can do their own research on this repo without stepping on each other. It exists because we hit the failure mode it prevents: the *same* fix (the AEDT `ddt()` output-var bug) was written independently on three branches, and the core machine model `machine_design/design2.py` has drifted into a different version on every branch. The rules below keep shared code shared and personal work personal. +A short guide so several people can work on this repo without stepping on each other. -## The one rule +## Repository layout -> **Shared code lives on `main` and is changed only by a small PR to `main`. -> Your research branch adds and edits only `experiments//`.** +| directory | contains | +|---|---| +| `machine_design/designs/` | the shared `Design`, `GeometryBase`, `ComputationBase` classes and `load_design()`, one FEA solve for a given machine | +| `machine_design/optimization/` | design agnostic optimizers and geometry generators | +| `machine_design/parallel_calculation/` | parallel runners for sweeping many solves at once | +| `motors/` | concrete machine definitions (`motor1.py`, `motor2.py`), each subclassing the base `Geometry`/`Computation` classes | +| `notebooks/` | entry point scripts (`run.py`, `run_optimization.py`) and analysis notebooks | +| `tests/` | the test suite | -If you find yourself editing `machine_design/` or `optimization/` on your own branch, stop — that's a change everyone needs, so it's a PR to `main`. Then rebase your branch on `main` and everyone gets the fix once. +Add a new machine by subclassing an existing `motors/motor*.py` file instead of editing an existing class in place, so old results stay reproducible. -## Three layers — what goes where +## Pull requests -| layer | directory | shared? | contains | -|---|---|---|---| -| **Designs** | `machine_design/` | yes (main) | *anchor* machines, geometry generators, and the one-solve FEA evaluation | -| **Methods** | `optimization/` | yes (main) | design-**agnostic** optimizers (BO, Thompson, nested, PFN…) that talk to designs only through the interface | -| **Experiments** | `experiments//` | no (your branch) | your run configs, the profile/objective you're studying, analysis notebooks, result artifacts, write-ups | +- Shared code changes go through a branch and a PR, not a direct push to `main`. +- Create the branch from the GitHub issue it belongs to ("Create a branch" in the issue's Development panel), so it is linked automatically. +- Commit, push, and open the PR with `Closes #` in the description. +- Make sure CI (Ruff and pytest) is green. +- Do not merge your own PR. Wait for review. -The point of the split: **a method should run on any design, and a design should be optimizable by any method.** Neither should import the other's internals — they meet at the interface (below). +## Running tests -## Anchor designs — named, frozen, *derived not forked* +Point at the Ansys install first, since the version and path differ per machine: -An **anchor** is a named, version-controlled machine definition — everything needed to instantiate and solve one physical machine: - -``` -class, slots, phases, winding (turns, Rs), end-winding Lew, rotor radii, -geometry generator + parameter bounds, FEA template +```bash +export ANSYSEM_ROOT241=/data/AnsysEM/v241/Linux64 ``` -Anchors live in `machine_design/anchors.py` (or `anchors/.yaml`) and are named `_f_s_t`, e.g. `synrm_5f_60s_113t` (the 500 W 5-phase machine). Rules: - -- **Derive, don't fork.** To study a variant (add magnets, change turns), *reference* an anchor and override only what differs — do **not** edit the anchor's class in place. A genuinely new machine is a **new anchor**, appended to the registry. -- **Anchors are append-only and shared.** A bug in an anchor's FEA (like the `ddt()` one) is fixed **once**, by a PR to `main`; everyone rebases and inherits it. No per-branch copies of `design2.py`. +Most tests do not need Ansys and run with: -## Methods and the design interface - -An optimizer in `optimization/` depends only on this contract, which every anchor implements: - -```python -sample_feasible_geometry() -> g # a valid rotor (normalized params) -geometry_bounds() -> (lb, ub) -evaluate(g, currents) -> dict # ONE FEA solve -> {T, ripple, flux, ...} -peak_current(currents) -> float # analytic constraints, no FEA +```bash +python -m pytest ``` -So `optimization/pathwise_thompson.py` never imports a specific design; you point it at `anchors.get("synrm_5f_60s_113t")` (or any other) and it runs. If you write a new method, put it here and it's instantly reusable by everyone. If you need a response the interface doesn't expose, extend the **interface** (a PR to main), not your method. - -## Branch & merge workflow +A few tests are marked `ansys` and need a running Ansys Electronics Desktop session with a free license seat, so they are skipped by default. Run them with: -- **`main` is the living trunk**, not a stale base. Keep it green; rebase onto it often. -- **Research branches are thin.** Name them `exp/` or `/` (e.g. `exp/reluctance-5f`, `vs/pfn-revisited`). They should almost never show a diff outside `experiments//`. -- **Shared-code change → PR to `main`.** Small, focused, reviewed by one other person. This is the whole discipline; everything else follows from it. -- Don't let a branch live for months without merging its shared parts back — that is how we got four divergent `design2.py`s. - -## Running things - -All compute goes through the SLURM queue on `bayes` — see [`bayes-queue/README.md`](bayes-queue/README.md). One FEA solve = 1 core + its own `--mem` + one license; submit sweeps as job arrays (`bayes-queue/sweep.sbatch`). - -## Quick checklists - -**I want to optimize an existing machine with an existing method** → in `experiments//`, write a config that picks an anchor + a method + your objective/constraints, and an sbatch to run it. Touch nothing shared. +```bash +python -m pytest -m "" -v +``` -**I want to study a new machine** → add an **anchor** (PR to `main`); if it's a variant, derive it from an existing anchor. Then use it from your experiment. +`-m ""` clears the default marker filter so the `ansys` tests are included too. -**I want a new optimization method** → add it to `optimization/` against the interface (PR to `main`). Now anyone can use it on any anchor. +## Running larger jobs -**I found a bug in a shared design/method** → fix it on `main` via PR, then rebase your branch. Do not patch it only on your branch. +All compute can also go through the SLURM queue on `bayes`, see [`bayes-queue/README.md`](bayes-queue/README.md). From 7067a8a7f75515a16efe096ca4b5e2367140a27c Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 3 Sep 2026 12:15:38 +0200 Subject: [PATCH 3/3] Simplify PR description guidance --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 44b0b9b..8565b66 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,7 @@ Add a new machine by subclassing an existing `motors/motor*.py` file instead of - Shared code changes go through a branch and a PR, not a direct push to `main`. - Create the branch from the GitHub issue it belongs to ("Create a branch" in the issue's Development panel), so it is linked automatically. -- Commit, push, and open the PR with `Closes #` in the description. +- Commit, push, and open the PR. Add a short description of what changed and why, and include `Closes #`. - Make sure CI (Ruff and pytest) is green. - Do not merge your own PR. Wait for review.