Skip to main content

Analytical electromechanical machine design library

Project description

emachines

Analytical electromechanical machine design library.

emachines is the core physics and mathematics engine behind emdesignlabs.com. It provides well-documented, tested, and citable implementations of the analytical models used in electric motor design.

Scope

  • Winding analysis — winding factors (kp, kd, kw), star-of-slots phasor method, slot/pole geometry, coil matrix
  • Magnetics — BH curve models (Fröhlich), iron loss (Steinmetz, Modified Steinmetz, Bertotti), electrical steel database
  • Motor models — PMSM dq-frame, surface-PM analytical design

Every function documents the equation it implements and its bibliographic source.

Installation

pip install emachines

For development (editable install alongside emdesignlabs):

pip install -e path/to/emachines

Quick Start

from emachines.winding.factors import winding_factor
from emachines.winding.sos import (
    get_basic_params, build_coil_matrix, winding_factor_sos,
    check_symmetry, get_valid_coil_spans
)
from emachines.magnetics.iron_loss import bertotti, fit_loss_model
from emachines.magnetics.electrical_steel import SteelDatabase, SAMPLE_LOSS
from emachines.motors.pmsm import PMSMParams, torque

# ── Winding factors ───────────────────────────────────────────────────────────

# Integer-slot: 24s/4p, 5/6 chording (closed-form kp × kd)
kw1 = winding_factor(nu=1, Q=24, p=2, coil_span=5)
print(f"kw1 (24s/4p chorded) = {kw1:.4f}")   # → 0.9330

# FSCW: 12s/10p, tooth-coil (star-of-slots phasor, auto-dispatched)
kw1 = winding_factor(nu=1, Q=12, p=5, coil_span=1)
print(f"kw1 (12s/10p FSCW)   = {kw1:.4f}")   # → 0.9330

# FSCW: 9s/8p
kw1 = winding_factor(nu=1, Q=9, p=4, coil_span=1)
print(f"kw1 (9s/8p FSCW)     = {kw1:.4f}")   # → 0.9452

# Winding geometry: classify a slot/pole combination
params = get_basic_params(Q=12, P=10)
print(params['winding_type'])    # → 'concentrated'
print(params['q'])               # → Fraction(2, 5)
print(check_symmetry(12, 10))   # → True

# Slot-conductor occupancy matrix (2 layers, tooth-coil span)
matrix = build_coil_matrix(Q=12, P=10, m=3, layers=2, w=1)
# matrix[layer, slot] = ±phase_index (1-indexed), shape (2, 12)

# Full harmonic spectrum via phasor method
from emachines.winding.sos import winding_factor_sos
for nu in [1, 3, 5, 7]:
    kw = winding_factor_sos(nu, Q=12, P=10, layers=2, w=1)
    print(f"  kw(ν={nu}) = {kw:.4f}")

# ── Iron loss ─────────────────────────────────────────────────────────────────

# Bertotti forward model at 400 Hz, 1.5 T
loss = bertotti(f=400, B_peak=1.5, k_h=0.02, k_e=1e-4, k_a=1e-3)
print(f"Total loss = {loss['total']:.2f} W/kg")
print(f"  Hysteresis: {loss['hysteresis']:.2f}  Eddy: {loss['eddy']:.2f}  Anomalous: {loss['anomalous']:.2f}")

# Fit Bertotti coefficients from measured data
import numpy as np
f_arr    = np.array([50, 100, 200, 400])
B_arr    = np.array([1.0, 1.0, 1.0, 1.0])
loss_arr = np.array([1.2, 2.8, 6.5, 15.1])
result = fit_loss_model(f_arr, B_arr, loss_arr, model="Bertotti")
print(f"k_h={result['k_h']:.4f}, k_e={result['k_e']:.2e}, R²={result['r2']:.4f}")

# ── Electrical steel database ─────────────────────────────────────────────────

# Load from manufacturer datasheets (data_dir is your local folder)
db = SteelDatabase("path/to/datasheets")
grade = db.load("M270-50A")
print(grade.loss_at(freq=200, B=1.5))   # W/kg interpolated from datasheet

# Built-in reference data — no files required
print(SAMPLE_LOSS["M-19"])   # DataFrame: loss vs frequency and flux density

# ── PMSM motor model ──────────────────────────────────────────────────────────

motor = PMSMParams(p=3, Ld=5e-3, Lq=8e-3, psi_m=0.15, Rs=0.1)
Te = torque(motor, id=-3.0, iq=10.0)
print(f"Torque = {Te:.2f} N·m")

Modules

emachines.winding

Module Contents
winding.factors pitch_factor, distribution_factor, winding_factor — integer-slot (closed-form) and FSCW (auto-dispatch to sos)
winding.sos build_star_of_slots, build_coil_matrix, assign_phases, winding_factor_sos — star-of-slots phasor method for all winding types; get_basic_params, check_symmetry, get_valid_coil_spans, is_valid_combination

Winding factor dispatch in winding_factor():

  • q ≥ 1 (integer-slot) → closed-form kp × kd
  • q < 1 (FSCW) → star-of-slots phasor sum, double-layer convention (matches emetor.com)

emachines.magnetics

Module Contents
magnetics.bh_models Fröhlich analytical BH model and curve fitting
magnetics.iron_loss steinmetz, modified_steinmetz, bertotti forward models; fit_steinmetz, fit_modified_steinmetz, fit_bertotti, fit_loss_model dispatcher
magnetics.electrical_steel SteelGrade dataclass, SteelDatabase (Voestalpine Excel + ThyssenKrupp/SURA pickle loaders, LRU-cached), SAMPLE_BH and SAMPLE_LOSS reference data

emachines.motors

Module Contents
motors.pmsm PMSMParams, back_emf, torque (excitation + reluctance), dq_currents

Design Philosophy

  • Equations first — every function documents the formula it implements with LaTeX notation
  • Cited — every formula traces back to a specific reference (textbook, paper, standard)
  • Tested — validated against published datasets and reference tools (emetor, SWAT-EM)
  • Dependency-light — only numpy, scipy, and pandas required

Test Coverage

Release Tests Status
0.3.0 92 ✅ All passing
0.2.0 36 ✅ All passing
0.1.0 18 ✅ All passing

Changelog

[0.3.0] — 2026-05-09

  • winding.sos: complete star-of-slots module — build_star_of_slots, build_coil_matrix, assign_phases, winding_factor_sos, get_basic_params, check_symmetry, get_valid_coil_spans, is_valid_combination
  • winding.factors: winding_factor() now dispatches to star-of-slots for FSCW (q < 1)
  • winding/__init__.py: all sos symbols exported at package level
  • 92 passing tests, 0 xfailed — FSCW winding factors fully supported
  • Validated against emetor.com: 12s/10p → 0.933, 9s/8p → 0.945, 12s/8p → 0.866

[0.2.0] — 2026-05-08

  • magnetics.electrical_steel: SteelGrade, SteelDatabase, SAMPLE_BH, SAMPLE_LOSS
  • magnetics.iron_loss: fit_bertotti, fit_steinmetz, fit_modified_steinmetz, fit_loss_model
  • pandas>=1.5 added as runtime dependency

[0.1.0] — 2026-05-07

  • winding.factors: pitch_factor, distribution_factor, winding_factor (integer-slot)
  • magnetics.bh_models: Fröhlich BH model and fitting
  • magnetics.iron_loss: steinmetz, modified_steinmetz, bertotti
  • motors.pmsm: PMSMParams, back_emf, torque, dq_currents

Status

0.3.x — Alpha. API may change between minor versions.

License

MIT

Publishing to PyPI

Use Docker so twine and build tools are always available regardless of the local Python environment:

cd /Users/nd/Documents/NewLight/emachines

docker run --rm -v "$(pwd):/src" -w /src python:3.12-slim bash -c "
  pip install twine build --quiet &&
  python -m build &&
  TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-<your-token> twine upload dist/emachines-<version>*
"

Replace <your-token> with your PyPI API token and <version> with the version in pyproject.toml (e.g. 0.4.0).

Steps before running:

  1. Bump version in pyproject.toml
  2. Add a release entry to CHANGELOG.md
  3. Commit and push to git
  4. Run the Docker command above

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

emachines-0.4.0.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

emachines-0.4.0-py3-none-any.whl (24.5 kB view details)

Uploaded Python 3

File details

Details for the file emachines-0.4.0.tar.gz.

File metadata

  • Download URL: emachines-0.4.0.tar.gz
  • Upload date:
  • Size: 27.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for emachines-0.4.0.tar.gz
Algorithm Hash digest
SHA256 67107e4343ae62b00d12f835e9a2ae482f9667c6743f842f357a688681e6eee6
MD5 f2be5f80dee445c8bf1eab8388b95889
BLAKE2b-256 43aa9c8128d44101731f0d2cc4bc431d026f0c619a1375e7a498d6c934f7923d

See more details on using hashes here.

File details

Details for the file emachines-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: emachines-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 24.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for emachines-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 756bb4b9437b7a7eaefbb3ba13b3381f406bf6114706621e860d8331711ddf97
MD5 e8772b1d80c3374314da4bddca63a837
BLAKE2b-256 6d1f34905eea67e79031dfbf9f69267c62bcad459c649f91b2eeb0e44a806fd4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page