Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
086817e
Added tests
sadda Jul 13, 2026
ea2f18d
Added tests on Ansys
sadda Jul 13, 2026
c50bbd0
Refactor
sadda Jul 13, 2026
af27a0d
Refactor
sadda Jul 13, 2026
edade44
Tests fixed
sadda Jul 13, 2026
11b8ade
FIxed tests
sadda Jul 13, 2026
341fc47
Bugfix
sadda Jul 13, 2026
33dfd4c
Refactor build_stator
sadda Jul 13, 2026
2186598
Refactor
sadda Jul 13, 2026
5bbdce3
Refactor
sadda Jul 13, 2026
3f0ae15
Improved appearance
sadda Jul 13, 2026
cc71430
Moved appearance
sadda Jul 13, 2026
9f3dbba
Simplified assign_stator_coils
sadda Jul 13, 2026
bb99e66
Simplified assign_stator_coils
sadda Jul 13, 2026
00c3448
Added safety check
sadda Jul 14, 2026
6b28a06
Changed names
sadda Jul 14, 2026
32b5963
Removed unused properties
sadda Jul 14, 2026
d6f1be3
Refactor
sadda Jul 14, 2026
dfc6048
Refactor
sadda Jul 14, 2026
8ef800f
Refactor
sadda Jul 14, 2026
650ddf9
Refactor
sadda Jul 14, 2026
b5c444e
fix: extract_results returns out instead of data
haitao-ZCU Jul 14, 2026
f392543
style: apply ruff formatting
haitao-ZCU Jul 14, 2026
fa5a0d8
Merge pull request #8 from AI-RICE/fix/extract-results-return-out
sadda Jul 14, 2026
13a25cd
ci: add pytest workflow
haitao-ZCU Jul 14, 2026
ace8daf
Move pandas, scipy, shapely into pyproject.toml dependencies
haitao-ZCU Jul 15, 2026
3e0ae73
Merge pull request #9 from AI-RICE/ci/add-pytest-workflow
sadda Jul 15, 2026
ee602ee
fix: convert units directly in extract_results
haitao-ZCU Jul 15, 2026
524dcbc
Returning whole array
sadda Jul 15, 2026
6ea9a92
Ruff
sadda Jul 15, 2026
826d95d
Merge pull request #10 from AI-RICE/fix/extract-results-unit-conversion
sadda Jul 15, 2026
9a745da
Added tests
sadda Sep 2, 2026
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
31 changes: 31 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Tests

on:
push:
branches:
- main
pull_request:

jobs:
pytest:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip

- name: Install package
run: pip install -e ".[dev]"

- name: Run tests
run: pytest
12 changes: 0 additions & 12 deletions machine_design/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +0,0 @@
from .design import Design
from .generators import (
FourStupid,
HacklGenerator_3BrokenLines,
HacklGenerator_OneLambda,
HacklGenerator_SixLambdas,
HacklGenerator_TwoLambdas,
save_params,
)
from .geometry import analyze_results, plot_barriers, rotate
from .load import load_design
from .optimization import init_points, objective, objective_single, objective_transform
2 changes: 2 additions & 0 deletions machine_design/designs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .design import Design
from .load import load_design
113 changes: 113 additions & 0 deletions machine_design/designs/computation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from abc import ABC, abstractmethod

from ansys.aedt.core import Maxwell2d

from .geometry import GeometryBase


class ComputationBase(ABC):
def __init__(self, geometry: GeometryBase) -> None:
self.geometry = geometry
self.setup_name = "Setup1"
self.set_oper_params()
self.set_solution_expressions()
self.set_output_vars()
self.set_post_params()

@abstractmethod
def set_oper_params(self): ...

@abstractmethod
def set_solution_expressions(self): ...

@abstractmethod
def set_output_vars(self): ...

@abstractmethod
def set_post_params(self): ...

@abstractmethod
def assign_stator_coils(self, m2d: Maxwell2d) -> None: ...

@abstractmethod
def inductance_computation(self, m2d: Maxwell2d) -> None: ...

@abstractmethod
def set_variables(self, m2d: Maxwell2d, *args): ...

@abstractmethod
def extract_results(self, solutions): ...

def push_variables(self, m2d: Maxwell2d) -> None:
for k, v in self.oper_params.items():
m2d[k] = v

def create_setup(self, m2d: Maxwell2d) -> None:
self.assign_stator_coils(m2d)
self.inductance_computation(m2d)

# model depth
m2d.model_depth = "StackLength"
# symmetry
m2d.change_symmetry_multiplier("SymmetryFactor")
# Calculation setup
setup = m2d.create_setup(name=self.setup_name)
setup.props["StopTime"] = "Nper/f"
setup.props["TimeStep"] = "1/(f*(PointPer-1))"
setup.props["SaveFieldsType"] = "None"
setup.props["OutputPerObjectCoreLoss"] = False
setup.props["OutputPerObjectSolidLoss"] = True
setup.props["OutputError"] = True
setup.update()
m2d.validate_simple()

for k, v in self.output_vars.items():
m2d.create_output_variable(k, v)

for k, v in self.post_params.items():
expressions = list(k) if isinstance(k, tuple) else [k] # if multiple report, use list(k). Else, use k
m2d.post.create_report(
expressions=expressions,
setup_sweep_name="",
domain="Sweep",
variations=None,
primary_sweep_variable="Time",
secondary_sweep_variable=None,
report_category=None,
plot_type="Rectangular Plot",
context=None,
subdesign_id=None,
polyline_points=1001,
plot_name=v,
)

# TODO: change the other arguments to kwargs
def compute(self, m2d: Maxwell2d, rotor_id, *args, NUM_CORES: int = 1):
assert m2d.mesh is not None
assert m2d.post is not None

m2d.mesh.assign_length_mesh(
assignment=rotor_id,
inside_selection=True,
maximum_length=3,
maximum_elements=None,
name="rotor",
)
# core loss rotor
m2d.set_core_losses("Rotor", core_loss_on_field=False)

self.set_variables(m2d, *args)

# Analyze
m2d.analyze_setup(self.setup_name, use_auto_settings=False, cores=NUM_CORES)

solutions = m2d.post.get_solution_data(expressions=self.solution_expressions, primary_sweep_variable="Time")
try:
result = self.extract_results(solutions)
except AttributeError:
result = None

# Delete solution data to prevent the saving size to explode
m2d.odesign.DeleteFullVariation("All", False)

return result
61 changes: 61 additions & 0 deletions machine_design/designs/design.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from ansys.aedt.core import Desktop, Maxwell2d

from .computation import ComputationBase
from .geometry import GeometryBase


class Design:
def __init__(self, m2d: Maxwell2d, geometry: GeometryBase, computation: ComputationBase) -> None:
assert computation.geometry is geometry
self.m2d = m2d
self.geometry = geometry
self.computation = computation

@classmethod
def create(cls, project_name: str, design_name: str, file_name: str, geometry: GeometryBase, computation: ComputationBase, **kwargs) -> "Design":
m2d = Maxwell2d(project=project_name, design=design_name, solution_type="TransientXY", **kwargs)
obj = cls(m2d, geometry, computation)
obj.add_stator()
obj.save_project(file_name)
return obj

@classmethod
def load(cls, file_name: str, geometry: GeometryBase, computation: ComputationBase, **kwargs) -> "Design":
desktop = Desktop(**kwargs)
desktop.load_project(file_name)

m2d = Maxwell2d()
m2d.set_active_design("Design01")

return cls(m2d, geometry, computation)

def add_stator(self) -> None:
self.computation.push_variables(self.m2d)
self.geometry.build_stator(self.m2d)
self.computation.create_setup(self.m2d)

def add_rotor(self) -> None:
self.geometry.build_rotor(self.m2d)

def add_rotor_barrier(self, barrier_points, segment_type=None) -> None:
self.geometry.add_rotor_barrier(self.m2d, barrier_points, segment_type)

def delete_rotor(self) -> None:
self.geometry.delete_rotor(self.m2d)

def compute(self, *args, NUM_CORES: int = 1):
return self.computation.compute(self.m2d, self.geometry.rotor_id, *args, NUM_CORES=NUM_CORES)

def save_design(self, file_name: str, **kwargs) -> None:
show = kwargs.pop("show", False)
view = kwargs.pop("view", "xy")
self.m2d.plot(show=show, output_file=file_name, view=view)

def save_project(self, file_name: str | None = None) -> None:
if file_name is None:
self.m2d.save_project()
else:
self.m2d.save_project(file_name)

def close_project(self) -> None:
self.m2d.close_desktop()
Loading
Loading