From 6a982d80515239cfcea309dffb5409e7813e6595 Mon Sep 17 00:00:00 2001 From: Polina Date: Tue, 22 Sep 2026 09:20:48 +0200 Subject: [PATCH 01/11] adding functions - magnets, CS system, material --- machine_design/designs/design.py | 3 ++ machine_design/designs/geometry.py | 77 ++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/machine_design/designs/design.py b/machine_design/designs/design.py index a16b5c4..bb5d023 100644 --- a/machine_design/designs/design.py +++ b/machine_design/designs/design.py @@ -40,6 +40,9 @@ def add_rotor(self) -> None: def add_rotor_barrier(self, barrier_points, segment_type=None) -> None: self.geometry.add_rotor_barrier(self.m2d, barrier_points, segment_type) + def add_rotor_magnet(self, magnet_points, segment_type=None) -> None: + self.geometry.add_rotor_magnet(self.m2d, magnet_points, segment_type) + def delete_rotor(self) -> None: self.computation.delete_rotor_mesh() self.geometry.delete_rotor(self.m2d) diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index 37c34ad..458769b 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -193,3 +193,80 @@ def _assign_boundary_conditions(self, m2d: Maxwell2d) -> None: assignment="Region", ) m2d.assign_vector_potential(assignment=id_bc_az, vector_value=0, boundary="A0") + + def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, segment_type=None): + modeler = m2d.modeler + fill_height = 0.9 + fill_width = 0.9 + + if isinstance(mag, (list, tuple)): + mag = np.concatenate([np.asarray(m) for m in mag], axis=0) + + pts = np.asarray(mag) + center = pts.mean(axis=0) + + r = np.linalg.norm(center) + if r < 1e-10: + return + + radial = center / r + long_axis = np.array([-radial[1], radial[0]]) + + pts_centered = pts - center + + proj_long = pts_centered @ long_axis + proj_short = pts_centered @ radial + + pts_scaled = center + ( + np.outer(proj_long * fill_height, long_axis) + + np.outer(proj_short * fill_width, radial) + ) + + points = [[f"{x}mm", f"{y}mm", "0mm"] for x, y in pts_scaled] + + mag_id = modeler.create_polyline( + points=points, + close_surface=True, + cover_surface=True, + name="Magnet", + ) + cs_angle_deg = np.degrees(np.arctan2(radial[1], radial[0])) + + self.assign_magnet_cs(m2d, mag_id, cs_angle_deg) + mag_id.material_name = material + mag_id.solve_inside = True + mag_id.color = (255, 0, 0) + mag_id.transparency = 0.0 + + modeler.set_working_coordinate_system("Global") + + def create_pm_material(self, m2d: Maxwell2d, PM: str) -> None: + if PM in m2d.materials.material_keys: + return m2d.materials[PM] + + mat = m2d.materials.add_material(PM) + mat.permeability = 1.05 + mat.conductivity = 0 + mat.mass_density = 7500 + mat.set_magnetic_coercivity( + value=900000, # A/m + x=1, + y=0, + z=0, + ) + + return mat + + def _create_magnet_cs(self, m2d: Maxwell2d, name: str, angle_deg: float) -> None: + m2d.modeler.create_coordinate_system( + origin=[0, 0, 0], + name=name, + mode="axis", + x_pointing=[float(np.cos(np.radians(angle_deg))), float(np.sin(np.radians(angle_deg))), 0], + y_pointing=[float(-np.sin(np.radians(angle_deg))), float(np.cos(np.radians(angle_deg))), 0], + ) + + def assign_magnet_cs(self, m2d: Maxwell2d, magnet_name: str, angle_deg: float) -> None: + cs_name = f"CS_{magnet_name}" + self._create_magnet_cs(m2d, cs_name, angle_deg) + m2d.modeler[magnet_name].part_coordinate_system = cs_name \ No newline at end of file From 764f2aadc6a743c1e5da88e6200b63a7f509ae1d Mon Sep 17 00:00:00 2001 From: Polina Date: Tue, 22 Sep 2026 09:28:46 +0200 Subject: [PATCH 02/11] Ruff format --- machine_design/designs/geometry.py | 119 ++++++++++++++--------------- 1 file changed, 58 insertions(+), 61 deletions(-) diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index 458769b..4da86bc 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -195,68 +195,65 @@ def _assign_boundary_conditions(self, m2d: Maxwell2d) -> None: m2d.assign_vector_potential(assignment=id_bc_az, vector_value=0, boundary="A0") def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, segment_type=None): - modeler = m2d.modeler - fill_height = 0.9 - fill_width = 0.9 - - if isinstance(mag, (list, tuple)): - mag = np.concatenate([np.asarray(m) for m in mag], axis=0) - - pts = np.asarray(mag) - center = pts.mean(axis=0) - - r = np.linalg.norm(center) - if r < 1e-10: - return - - radial = center / r - long_axis = np.array([-radial[1], radial[0]]) - - pts_centered = pts - center - - proj_long = pts_centered @ long_axis - proj_short = pts_centered @ radial - - pts_scaled = center + ( - np.outer(proj_long * fill_height, long_axis) + - np.outer(proj_short * fill_width, radial) - ) - - points = [[f"{x}mm", f"{y}mm", "0mm"] for x, y in pts_scaled] - - mag_id = modeler.create_polyline( - points=points, - close_surface=True, - cover_surface=True, - name="Magnet", - ) - cs_angle_deg = np.degrees(np.arctan2(radial[1], radial[0])) - - self.assign_magnet_cs(m2d, mag_id, cs_angle_deg) - mag_id.material_name = material - mag_id.solve_inside = True - mag_id.color = (255, 0, 0) - mag_id.transparency = 0.0 - - modeler.set_working_coordinate_system("Global") + modeler = m2d.modeler + fill_height = 0.9 + fill_width = 0.9 + + if isinstance(mag, (list, tuple)): + mag = np.concatenate([np.asarray(m) for m in mag], axis=0) + + pts = np.asarray(mag) + center = pts.mean(axis=0) + + r = np.linalg.norm(center) + if r < 1e-10: + return + + radial = center / r + long_axis = np.array([-radial[1], radial[0]]) + + pts_centered = pts - center + + proj_long = pts_centered @ long_axis + proj_short = pts_centered @ radial + + pts_scaled = center + (np.outer(proj_long * fill_height, long_axis) + np.outer(proj_short * fill_width, radial)) + + points = [[f"{x}mm", f"{y}mm", "0mm"] for x, y in pts_scaled] + + mag_id = modeler.create_polyline( + points=points, + close_surface=True, + cover_surface=True, + name="Magnet", + ) + cs_angle_deg = np.degrees(np.arctan2(radial[1], radial[0])) + + self.assign_magnet_cs(m2d, mag_id, cs_angle_deg) + mag_id.material_name = material + mag_id.solve_inside = True + mag_id.color = (255, 0, 0) + mag_id.transparency = 0.0 + + modeler.set_working_coordinate_system("Global") def create_pm_material(self, m2d: Maxwell2d, PM: str) -> None: - if PM in m2d.materials.material_keys: - return m2d.materials[PM] - - mat = m2d.materials.add_material(PM) - mat.permeability = 1.05 - mat.conductivity = 0 - mat.mass_density = 7500 - mat.set_magnetic_coercivity( - value=900000, # A/m - x=1, - y=0, - z=0, - ) - - return mat - + if PM in m2d.materials.material_keys: + return m2d.materials[PM] + + mat = m2d.materials.add_material(PM) + mat.permeability = 1.05 + mat.conductivity = 0 + mat.mass_density = 7500 + mat.set_magnetic_coercivity( + value=900000, # A/m + x=1, + y=0, + z=0, + ) + + return mat + def _create_magnet_cs(self, m2d: Maxwell2d, name: str, angle_deg: float) -> None: m2d.modeler.create_coordinate_system( origin=[0, 0, 0], @@ -269,4 +266,4 @@ def _create_magnet_cs(self, m2d: Maxwell2d, name: str, angle_deg: float) -> None def assign_magnet_cs(self, m2d: Maxwell2d, magnet_name: str, angle_deg: float) -> None: cs_name = f"CS_{magnet_name}" self._create_magnet_cs(m2d, cs_name, angle_deg) - m2d.modeler[magnet_name].part_coordinate_system = cs_name \ No newline at end of file + m2d.modeler[magnet_name].part_coordinate_system = cs_name From 1ad781d2e9e28c9a09a8a44d22d0dc2e5ff1cedc Mon Sep 17 00:00:00 2001 From: Polina Date: Wed, 30 Sep 2026 11:05:37 +0200 Subject: [PATCH 03/11] added universal create_material --- machine_design/designs/geometry.py | 38 +++++++++++++++++------------- motors/synrm_3f_36s.py | 10 ++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index 4da86bc..110c8f3 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -194,10 +194,8 @@ def _assign_boundary_conditions(self, m2d: Maxwell2d) -> None: ) m2d.assign_vector_potential(assignment=id_bc_az, vector_value=0, boundary="A0") - def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, segment_type=None): + def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, fill_height=0.9, fill_width=0.9, segment_type=None): modeler = m2d.modeler - fill_height = 0.9 - fill_width = 0.9 if isinstance(mag, (list, tuple)): mag = np.concatenate([np.asarray(m) for m in mag], axis=0) @@ -237,20 +235,26 @@ def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, segment_ty modeler.set_working_coordinate_system("Global") - def create_pm_material(self, m2d: Maxwell2d, PM: str) -> None: - if PM in m2d.materials.material_keys: - return m2d.materials[PM] - - mat = m2d.materials.add_material(PM) - mat.permeability = 1.05 - mat.conductivity = 0 - mat.mass_density = 7500 - mat.set_magnetic_coercivity( - value=900000, # A/m - x=1, - y=0, - z=0, - ) + def create_material( + self, + m2d: Maxwell2d, + name: str, + permeability: float, + conductivity: float, + density: float, + coercivity: float | None = None, + coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), + ) -> None: + if name in m2d.materials.material_keys: + return m2d.materials[name] + + mat = m2d.materials.add_material(name) + mat.permeability = permeability + mat.conductivity = conductivity + mat.mass_density = density + + if coercivity is not None: + mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) return mat diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index c8f4b65..22d80df 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -12,6 +12,16 @@ class Geometry(GeometryBase): def set_iron(self): self.Fe = "Cogent Power - M350-50A, B-H at 50Hz" + def set_magnets(self): + self.Magnet = GeometryBase.create_material( + name="NdFeb", + permeability=1.05, + conductivity=0, + density=7500, + coercivity=900000, + coercivity_dir=(1.0, 0.0, 0.0), + ) + def set_geom_params(self): self.geom_params = { "DiaStatorGap": "79mm", From 70554fe5d9463f0ba29b0b75eb2360f3cc1d3d43 Mon Sep 17 00:00:00 2001 From: Polina Date: Wed, 30 Sep 2026 12:53:00 +0200 Subject: [PATCH 04/11] fixed and error --- machine_design/designs/geometry.py | 29 ++++------------------ motors/synrm_3f_36s.py | 35 +++++++++++++++++++++------ scripts/3f_torque_optimization/run.py | 2 +- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index 110c8f3..eb3add5 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -10,6 +10,7 @@ class GeometryBase(ABC): def __init__(self) -> None: self.set_iron() + self.set_magnets() self.set_geom_params() self.set_slot_params() self.set_winds_params() @@ -22,6 +23,9 @@ def __init__(self) -> None: @abstractmethod def set_iron(self): ... + @abstractmethod + def set_magnets(self): ... + @abstractmethod def set_geom_params(self): ... @@ -228,36 +232,13 @@ def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, fill_heigh cs_angle_deg = np.degrees(np.arctan2(radial[1], radial[0])) self.assign_magnet_cs(m2d, mag_id, cs_angle_deg) - mag_id.material_name = material + mag_id.material_name = self.magnet mag_id.solve_inside = True mag_id.color = (255, 0, 0) mag_id.transparency = 0.0 modeler.set_working_coordinate_system("Global") - def create_material( - self, - m2d: Maxwell2d, - name: str, - permeability: float, - conductivity: float, - density: float, - coercivity: float | None = None, - coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), - ) -> None: - if name in m2d.materials.material_keys: - return m2d.materials[name] - - mat = m2d.materials.add_material(name) - mat.permeability = permeability - mat.conductivity = conductivity - mat.mass_density = density - - if coercivity is not None: - mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) - - return mat - def _create_magnet_cs(self, m2d: Maxwell2d, name: str, angle_deg: float) -> None: m2d.modeler.create_coordinate_system( origin=[0, 0, 0], diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index 22d80df..81a33fc 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -13,14 +13,9 @@ def set_iron(self): self.Fe = "Cogent Power - M350-50A, B-H at 50Hz" def set_magnets(self): - self.Magnet = GeometryBase.create_material( - name="NdFeb", - permeability=1.05, - conductivity=0, - density=7500, - coercivity=900000, - coercivity_dir=(1.0, 0.0, 0.0), - ) + self.magnet = "NdFeb" + self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, + coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) def set_geom_params(self): self.geom_params = { @@ -110,6 +105,7 @@ def build_stator(self, m2d: Maxwell2d) -> None: self._split_for_symmetry(m2d, [stator_id, shaft_id, region_id, band_id]) self._assign_boundary_conditions(m2d) self._assign_stator_mesh(m2d, stator_id, id_coils) + self._create_material(m2d, self.magnet, **self.magnet_props) # core loss m2d.set_core_losses("Stator", core_loss_on_field=False) @@ -120,6 +116,29 @@ def build_stator(self, m2d: Maxwell2d) -> None: self.band_id = band_id self.id_coils = id_coils + def _create_material( + self, + m2d: Maxwell2d, + name: str, + permeability: float, + conductivity: float, + density: float, + coercivity: float | None = None, + coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), + ) -> None: + if name in m2d.materials.material_keys: + return m2d.materials[name] + + mat = m2d.materials.add_material(name) + mat.permeability = permeability + mat.conductivity = conductivity + mat.mass_density = density + + if coercivity is not None: + mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) + + return mat + def _assign_rotor_motion(self, m2d: Maxwell2d) -> None: m2d.assign_rotate_motion( assignment="Band", diff --git a/scripts/3f_torque_optimization/run.py b/scripts/3f_torque_optimization/run.py index 4f50fbe..c0d5380 100644 --- a/scripts/3f_torque_optimization/run.py +++ b/scripts/3f_torque_optimization/run.py @@ -83,4 +83,4 @@ metadata = pd.concat((metadata, pd.DataFrame([metadata_new])), ignore_index=True) metadata.to_csv(f"{path_results}/metadata.csv", index=False) -design.close_project() +design.close_project() \ No newline at end of file From 0b69113482449a4d3bfe0f64260a4d966ef05ef4 Mon Sep 17 00:00:00 2001 From: Polina Date: Thu, 1 Oct 2026 10:16:48 +0200 Subject: [PATCH 05/11] ruff format --- machine_design/designs/geometry.py | 4 - motors/synrm_3f_36s_mag.py | 298 ++++++++++++++++++++++++++ scripts/3f_torque_optimization/run.py | 2 +- 3 files changed, 299 insertions(+), 5 deletions(-) create mode 100644 motors/synrm_3f_36s_mag.py diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index eb3add5..2a07d06 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -10,7 +10,6 @@ class GeometryBase(ABC): def __init__(self) -> None: self.set_iron() - self.set_magnets() self.set_geom_params() self.set_slot_params() self.set_winds_params() @@ -23,9 +22,6 @@ def __init__(self) -> None: @abstractmethod def set_iron(self): ... - @abstractmethod - def set_magnets(self): ... - @abstractmethod def set_geom_params(self): ... diff --git a/motors/synrm_3f_36s_mag.py b/motors/synrm_3f_36s_mag.py new file mode 100644 index 0000000..1fb2673 --- /dev/null +++ b/motors/synrm_3f_36s_mag.py @@ -0,0 +1,298 @@ +"""Anchor `synrm_3f_36s`: 3-phase synchronous reluctance machine, 36 stator slots.""" + +import numpy as np +from ansys.aedt.core import Maxwell2d +from ansys.aedt.core.modeler.modeler_2d import Modeler2D + +from machine_design.designs.computation import ComputationBase +from machine_design.designs.geometry import GeometryBase + + +class Geometry(GeometryBase): + def set_iron(self): + self.Fe = "Cogent Power - M350-50A, B-H at 50Hz" + + def set_magnets(self): + self.magnet = "NdFeb" + self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) + + def set_geom_params(self): + self.geom_params = { + "DiaStatorGap": "79mm", + "DiaStatorYoke": "125mm", + "Airgap": "0.225mm", + "SlotNumber": "36", + "SlotType": "3", + "DiaShaft": "25mm", + "StackLength": "85mm", + } + + def set_slot_params(self): + self.slot_params = { + "Hs0": "0.95mm", + "Hs1": "0.31mm", + "Hs2": "8.24mm", + "Bs0": "2.2mm", + "Bs1": "3.37mm", + "Bs2": "4.8mm", + "Rs": "1.5mm", + "SetAngle": "10deg", + } + + def set_winds_params(self): + self.wind_params = { + "Layers": "1", + "ParallelPaths": "1", + "CoilPitch": "9", # coil pitch in slots + "SlotLiner": "0.3mm", + "SpaceLayers": "0.2mm", + "Nc": "68", # turns per coil + } + + def set_mod_params(self): + self.PolePairs = 2 + self.mod_params = { + "Poles": f"2*{self.PolePairs}", + "ModelLength": "85mm", + "SymmetryFactor": "Poles", + "StatorSkewAngle": "0deg", + } + + def set_rot_points(self): + self.rot_points = [ + ["DiaShaft/2*cos(360deg/SymmetryFactor)", "DiaShaft/2*sin(360deg/SymmetryFactor)", "0mm"], + ["DiaShaft/2*cos(360deg/(2*SymmetryFactor))", "DiaShaft/2*sin(360deg/(2*SymmetryFactor))", "0mm"], + ["DiaShaft/2", "0mm", "0mm"], + ["DiaStatorGap/2-Airgap", "0mm", "0mm"], + ["(DiaStatorGap/2-Airgap)*cos(360deg/(2*SymmetryFactor))", "(DiaStatorGap/2-Airgap)*sin(360deg/(2*SymmetryFactor))", "0mm"], + ["(DiaStatorGap/2-Airgap)*cos(360deg/SymmetryFactor)", "(DiaStatorGap/2-Airgap)*sin(360deg/SymmetryFactor)", "0mm"], + ] + + def set_derived_params(self): + self.rotor_r_min = self.mm_to_str("geom_params", "DiaShaft") / 2 + self.rotor_r_max = self.mm_to_str("geom_params", "DiaStatorGap") / 2 - self.mm_to_str("geom_params", "Airgap") + + def set_udp_par_list_stator(self): + self.udp_par_list_stator = [ + ["DiaGap", "DiaStatorGap"], + ["DiaYoke", "DiaStatorYoke"], + ["Length", "0mm"], + ["Skew", "0deg"], + ["Slots", "SlotNumber"], + ["SlotType", "SlotType"], + ["Hs0", "Hs0"], + ["Hs01", "0mm"], + ["Hs1", "Hs1"], + ["Hs2", "Hs2"], + ["Bs0", "Bs0"], + ["Bs1", "Bs1"], + ["Bs2", "Bs2"], + ["Rs", "Rs"], + ["FilletType", "0"], + ["HalfSlot", "0"], + ["SegAngle", "0deg"], + ["LenRegion", "0mm"], + ["InfoCore", "0"], + ] + + def build_stator(self, m2d: Maxwell2d) -> None: + self._push_stator_variables(m2d) + shaft_id, region_id, band_id = self._build_vacuum_regions(m2d) + self._assign_rotor_motion(m2d) + stator_id = self._build_stator_core(m2d) + id_coils = self._build_stator_coils(m2d) + self._split_for_symmetry(m2d, [stator_id, shaft_id, region_id, band_id]) + self._assign_boundary_conditions(m2d) + self._assign_stator_mesh(m2d, stator_id, id_coils) + self._create_material(m2d, self.magnet, **self.magnet_props) + + # core loss + m2d.set_core_losses("Stator", core_loss_on_field=False) + + self.stator_id = stator_id + self.shaft_id = shaft_id + self.region_id = region_id + self.band_id = band_id + self.id_coils = id_coils + + def _create_material( + self, + m2d: Maxwell2d, + name: str, + permeability: float, + conductivity: float, + density: float, + coercivity: float | None = None, + coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), + ) -> None: + if name in m2d.materials.material_keys: + return m2d.materials[name] + + mat = m2d.materials.add_material(name) + mat.permeability = permeability + mat.conductivity = conductivity + mat.mass_density = density + + if coercivity is not None: + mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) + + return mat + + def _assign_rotor_motion(self, m2d: Maxwell2d) -> None: + m2d.assign_rotate_motion( + assignment="Band", + coordinate_system="Global", + axis="Z", + positive_movement=True, + start_position="InitPos", + angular_velocity="RotSpeed", + has_rotation_limits=False, + ) + + def _build_stator_core(self, m2d: Maxwell2d): + modeler = m2d.modeler + assert isinstance(modeler, Modeler2D) + + stator_id = modeler.create_udp( + dll="RMxprt/SlotCore.dll", + parameters=self.udp_par_list_stator, + library="syslib", + name="Stator", + # SolveInside="True", + ) + stator_id.material_name = self.Fe + + return stator_id + + def _build_stator_coils(self, m2d: Maxwell2d): + modeler = m2d.modeler + assert isinstance(modeler, Modeler2D) + + coil_id = modeler.create_rectangle( + origin=["DiaStatorGap/2+Hs0+Hs1+SlotLiner", "-(Bs1/2-SlotLiner)", 0], + sizes=["(Hs2+Rs/2-2*SlotLiner)/Layers-(Layers-1)*SpaceLayers/2", "Bs1-2*SlotLiner", 0], + name="Coil", + material="copper", + ) + modeler.rotate(assignment=coil_id, axis="Z", angle="360deg/SlotNumber/2") + coil_id.duplicate_around_axis(axis="Z", angle="360deg/SlotNumber", clones="SlotNumber/Poles", create_new_objects=True) + id_coils = modeler.get_objects_w_string(string_name="Coil", case_sensitive=True) + + return id_coils + + def _assign_stator_mesh(self, m2d: Maxwell2d, stator_id, id_coils) -> None: + m2d.mesh.assign_length_mesh( + assignment=id_coils, + inside_selection=True, + maximum_length=3, + maximum_elements=None, + name="coils", + ) + m2d.mesh.assign_length_mesh( + assignment=stator_id, + inside_selection=True, + maximum_length=3, + maximum_elements=None, + name="stator", + ) + + +class Computation(ComputationBase): + def set_oper_params(self): + f = 50 # [Hz] + RotSpeed = 60 * f / self.geometry.PolePairs # [rpm] + w = 2 * np.pi * f + self.oper_params = { + "Im": "1.5*sqrt(2)A", + "epsI": "pi/4", # current angle + "InitPos": "-30deg", + "w": f"{w}Hz", + "RotSpeed": f"{RotSpeed}rpm", + "Nper": "1/6", # number of included periods + "PointPer": "101", # number of time points per period + } + + def set_solution_expressions(self): + self.solution_expressions = "Moving1.Torque" + + def set_output_vars(self): + self.output_vars = { + "pos": "(Moving1.Position -InitPos) * Poles/2", + "cos0": "cos(pos)", + "cos1": "cos(pos-2*PI/3)", + "cos2": "cos(pos-4*PI/3)", + "sin0": "sin(pos)", + "sin1": "sin(pos-2*PI/3)", + "sin2": "sin(pos-4*PI/3)", + "Lad": "L(PhaseA,PhaseA)*cos0 + L(PhaseA,PhaseB)*cos1 + L(PhaseA,PhaseC)*cos2", + "Laq": "L(PhaseA,PhaseA)*sin0 + L(PhaseA,PhaseB)*sin1 + L(PhaseA,PhaseC)*sin2", + "Lbd": "L(PhaseB,PhaseA)*cos0 + L(PhaseB,PhaseB)*cos1 + L(PhaseB,PhaseC)*cos2", + "Lbq": "L(PhaseB,PhaseA)*sin0 + L(PhaseB,PhaseB)*sin1 + L(PhaseB,PhaseC)*sin2", + "Lcd": "L(PhaseC,PhaseA)*cos0 + L(PhaseC,PhaseB)*cos1 + L(PhaseC,PhaseC)*cos2", + "Lcq": "L(PhaseC,PhaseA)*sin0 + L(PhaseC,PhaseB)*sin1 + L(PhaseC,PhaseC)*sin2", + "L_d": "(Lad*cos0 + Lbd*cos1 + Lcd*cos2) * 2/3", + "L_q": "(Laq*sin0 + Lbq*sin1 + Lcq*sin2) * 2/3", + "Flux_d": "(FluxLinkage(PhaseA)*cos0+FluxLinkage(PhaseB)*cos1+FluxLinkage(PhaseC)*cos2)*2/3", + "Flux_q": "-(FluxLinkage(PhaseA)*sin0+FluxLinkage(PhaseB)*sin1+FluxLinkage(PhaseC)*sin2)*2/3", + "Ui_d": "(InducedVoltage(PhaseA)*cos0+InducedVoltage(PhaseB)*cos1+InducedVoltage(PhaseC)*cos2)*2/3", + "Ui_q": "-(InducedVoltage(PhaseA)*sin0+InducedVoltage(PhaseB)*sin1+InducedVoltage(PhaseC)*sin2)*2/3", + "I_d": "(InputCurrent(PhaseA)*cos0 + InputCurrent(PhaseB)*cos1 + InputCurrent(PhaseC)*cos2)*2/3", + "I_q": "-(InputCurrent(PhaseA)*sin0 + InputCurrent(PhaseB)*sin1 + InputCurrent(PhaseC)*sin2)*2/3", + "Irms": "sqrt(I_d^2+I_q^2)/sqrt(2)", + } + + def set_post_params(self): + self.post_params = { # reports + ("InducedVoltage(PhaseA)", "InducedVoltage(PhaseB)", "InducedVoltage(PhaseC)"): "InducedVoltage", + ("Moving1.Torque"): "Torque", + ("InputCurrent(PhaseA)", "InputCurrent(PhaseB)", "InputCurrent(PhaseC)"): "Current", + ( + "FluxLinkage(PhaseA)", + "FluxLinkage(PhaseB)", + "FluxLinkage(PhaseC)", + ): "FluxLinkage", + ("I_d", "I_q"): "Current_dq", + ("Flux_d", "Flux_q"): "FluxLinkage_dq", + ("Ui_d", "Ui_q"): "InducedVoltage_dq", + ("L_d", "L_q"): "Inductance_dq", + } + + def assign_stator_coils(self, m2d: Maxwell2d) -> None: + # Excitations + I_A = "Im * cos(w*Time+epsI)" + I_B = "Im * cos(w*Time-120deg+epsI)" + I_C = "Im * cos(w*Time-240deg+epsI)" + + phases_polarity = ["Positive", "Negative", "Positive"] + phases_name = ["A", "C", "B"] + phases_current = [I_A, I_C, I_B] + i_coil = 0 + for phase_polarity, phase_name, phase_current in zip(phases_polarity, phases_name, phases_current): + names = [] + for _ in range(3): + m2d.assign_coil( + assignment=[self.geometry.id_coils[i_coil]], + conductors_number="Nc", + polarity=phase_polarity, + name=f"CS{i_coil + 1}", + ) + names.append(f"CS{i_coil + 1}") + i_coil += 1 + m2d.assign_winding( + assignment=None, + winding_type="Current", + is_solid=False, + current=phase_current, + parallel_branches="ParallelPaths", + name=f"Phase{phase_name}", + ) + m2d.add_winding_coils(assignment=f"Phase{phase_name}", coils=names) + + def inductance_computation(self, m2d: Maxwell2d) -> None: + m2d.change_inductance_computation(compute_transient_inductance=True, incremental_matrix=False) + + def set_variables(self, m2d: Maxwell2d, *args): + pass + + def extract_results(self, solutions): + return solutions.data_magnitude() diff --git a/scripts/3f_torque_optimization/run.py b/scripts/3f_torque_optimization/run.py index c0d5380..4f50fbe 100644 --- a/scripts/3f_torque_optimization/run.py +++ b/scripts/3f_torque_optimization/run.py @@ -83,4 +83,4 @@ metadata = pd.concat((metadata, pd.DataFrame([metadata_new])), ignore_index=True) metadata.to_csv(f"{path_results}/metadata.csv", index=False) -design.close_project() \ No newline at end of file +design.close_project() From 2a18a55ad03926ae1a4d62b6c96c51322a93ee48 Mon Sep 17 00:00:00 2001 From: Polina Date: Tue, 6 Oct 2026 10:23:44 +0200 Subject: [PATCH 06/11] fixing errors --- machine_design/designs/design.py | 2 +- machine_design/designs/geometry.py | 31 +++++++++++++++++++++++++++++- motors/synrm_3f_36s.py | 28 --------------------------- motors/synrm_3f_36s_mag.py | 27 -------------------------- 4 files changed, 31 insertions(+), 57 deletions(-) diff --git a/machine_design/designs/design.py b/machine_design/designs/design.py index bb5d023..8bdb757 100644 --- a/machine_design/designs/design.py +++ b/machine_design/designs/design.py @@ -41,7 +41,7 @@ def add_rotor_barrier(self, barrier_points, segment_type=None) -> None: self.geometry.add_rotor_barrier(self.m2d, barrier_points, segment_type) def add_rotor_magnet(self, magnet_points, segment_type=None) -> None: - self.geometry.add_rotor_magnet(self.m2d, magnet_points, segment_type) + self.geometry.add_rotor_magnet(self.m2d, magnet_points, segment_type=segment_type) def delete_rotor(self) -> None: self.computation.delete_rotor_mesh() diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index 2a07d06..b22d643 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -10,6 +10,7 @@ class GeometryBase(ABC): def __init__(self) -> None: self.set_iron() + self.set_magnets() self.set_geom_params() self.set_slot_params() self.set_winds_params() @@ -194,7 +195,7 @@ def _assign_boundary_conditions(self, m2d: Maxwell2d) -> None: ) m2d.assign_vector_potential(assignment=id_bc_az, vector_value=0, boundary="A0") - def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, fill_height=0.9, fill_width=0.9, segment_type=None): + def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, fill_height=0.9, fill_width=0.9, segment_type=None): modeler = m2d.modeler if isinstance(mag, (list, tuple)): @@ -228,6 +229,7 @@ def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, material, fill_heigh cs_angle_deg = np.degrees(np.arctan2(radial[1], radial[0])) self.assign_magnet_cs(m2d, mag_id, cs_angle_deg) + self._create_material(m2d, self.magnet, **self.magnet_props) mag_id.material_name = self.magnet mag_id.solve_inside = True mag_id.color = (255, 0, 0) @@ -248,3 +250,30 @@ def assign_magnet_cs(self, m2d: Maxwell2d, magnet_name: str, angle_deg: float) - cs_name = f"CS_{magnet_name}" self._create_magnet_cs(m2d, cs_name, angle_deg) m2d.modeler[magnet_name].part_coordinate_system = cs_name + + def set_magnets(self): + self.magnet = "NdFeb" + self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) + + def _create_material( + self, + m2d: Maxwell2d, + name: str, + permeability: float, + conductivity: float, + density: float, + coercivity: float | None = None, + coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), + ): + if name.lower() in m2d.materials.material_keys: + return m2d.materials[name] + + mat = m2d.materials.add_material(name) + mat.permeability = permeability + mat.conductivity = conductivity + mat.mass_density = density + + if coercivity is not None: + mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) + + return mat diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index 2795fdb..e069c1f 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -13,11 +13,6 @@ class Geometry(GeometryBase): def set_iron(self): self.Fe = "Cogent Power - M350-50A, B-H at 50Hz" - def set_magnets(self): - self.magnet = "NdFeb" - self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, - coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) - def set_geom_params(self): self.geom_params = { "DiaStatorGap": "79mm", @@ -117,29 +112,6 @@ def build_stator(self, m2d: Maxwell2d) -> None: self.band_id = band_id self.id_coils = id_coils - def _create_material( - self, - m2d: Maxwell2d, - name: str, - permeability: float, - conductivity: float, - density: float, - coercivity: float | None = None, - coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), - ) -> None: - if name in m2d.materials.material_keys: - return m2d.materials[name] - - mat = m2d.materials.add_material(name) - mat.permeability = permeability - mat.conductivity = conductivity - mat.mass_density = density - - if coercivity is not None: - mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) - - return mat - def _assign_rotor_motion(self, m2d: Maxwell2d) -> None: m2d.assign_rotate_motion( assignment="Band", diff --git a/motors/synrm_3f_36s_mag.py b/motors/synrm_3f_36s_mag.py index 1fb2673..ca5605d 100644 --- a/motors/synrm_3f_36s_mag.py +++ b/motors/synrm_3f_36s_mag.py @@ -12,10 +12,6 @@ class Geometry(GeometryBase): def set_iron(self): self.Fe = "Cogent Power - M350-50A, B-H at 50Hz" - def set_magnets(self): - self.magnet = "NdFeb" - self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) - def set_geom_params(self): self.geom_params = { "DiaStatorGap": "79mm", @@ -115,29 +111,6 @@ def build_stator(self, m2d: Maxwell2d) -> None: self.band_id = band_id self.id_coils = id_coils - def _create_material( - self, - m2d: Maxwell2d, - name: str, - permeability: float, - conductivity: float, - density: float, - coercivity: float | None = None, - coercivity_dir: tuple[float, float, float] = (0.0, 0.0, 0.0), - ) -> None: - if name in m2d.materials.material_keys: - return m2d.materials[name] - - mat = m2d.materials.add_material(name) - mat.permeability = permeability - mat.conductivity = conductivity - mat.mass_density = density - - if coercivity is not None: - mat.set_magnetic_coercivity(value=coercivity, x=coercivity_dir[0], y=coercivity_dir[1], z=coercivity_dir[2]) - - return mat - def _assign_rotor_motion(self, m2d: Maxwell2d) -> None: m2d.assign_rotate_motion( assignment="Band", From 29c51dda95ea03fad524153f838490b32016363e Mon Sep 17 00:00:00 2001 From: Polina Date: Tue, 6 Oct 2026 11:09:35 +0200 Subject: [PATCH 07/11] deleted extra line --- motors/synrm_3f_36s.py | 1 - 1 file changed, 1 deletion(-) diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index e069c1f..812a051 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -101,7 +101,6 @@ def build_stator(self, m2d: Maxwell2d) -> None: self._split_for_symmetry(m2d, [stator_id, shaft_id, region_id, band_id]) self._assign_boundary_conditions(m2d) self._assign_stator_mesh(m2d, stator_id, id_coils) - self._create_material(m2d, self.magnet, **self.magnet_props) # core loss m2d.set_core_losses("Stator", core_loss_on_field=False) From 14e3d60aad1e96648595992ebd80f91a2fcdd985 Mon Sep 17 00:00:00 2001 From: sadda Date: Tue, 6 Oct 2026 10:22:01 +0000 Subject: [PATCH 08/11] Simplification --- motors/synrm_3f_36s_mag.py | 234 ++++--------------------------------- 1 file changed, 20 insertions(+), 214 deletions(-) diff --git a/motors/synrm_3f_36s_mag.py b/motors/synrm_3f_36s_mag.py index ca5605d..40bf47d 100644 --- a/motors/synrm_3f_36s_mag.py +++ b/motors/synrm_3f_36s_mag.py @@ -2,176 +2,21 @@ import numpy as np from ansys.aedt.core import Maxwell2d -from ansys.aedt.core.modeler.modeler_2d import Modeler2D -from machine_design.designs.computation import ComputationBase -from machine_design.designs.geometry import GeometryBase +from motors.synrm_3f_36s import Computation as Computation3f36s +from motors.synrm_3f_36s import Geometry as Geometry3f36s +__all__ = ["Geometry", "Computation"] -class Geometry(GeometryBase): - def set_iron(self): - self.Fe = "Cogent Power - M350-50A, B-H at 50Hz" - - def set_geom_params(self): - self.geom_params = { - "DiaStatorGap": "79mm", - "DiaStatorYoke": "125mm", - "Airgap": "0.225mm", - "SlotNumber": "36", - "SlotType": "3", - "DiaShaft": "25mm", - "StackLength": "85mm", - } - - def set_slot_params(self): - self.slot_params = { - "Hs0": "0.95mm", - "Hs1": "0.31mm", - "Hs2": "8.24mm", - "Bs0": "2.2mm", - "Bs1": "3.37mm", - "Bs2": "4.8mm", - "Rs": "1.5mm", - "SetAngle": "10deg", - } - - def set_winds_params(self): - self.wind_params = { - "Layers": "1", - "ParallelPaths": "1", - "CoilPitch": "9", # coil pitch in slots - "SlotLiner": "0.3mm", - "SpaceLayers": "0.2mm", - "Nc": "68", # turns per coil - } - - def set_mod_params(self): - self.PolePairs = 2 - self.mod_params = { - "Poles": f"2*{self.PolePairs}", - "ModelLength": "85mm", - "SymmetryFactor": "Poles", - "StatorSkewAngle": "0deg", - } - - def set_rot_points(self): - self.rot_points = [ - ["DiaShaft/2*cos(360deg/SymmetryFactor)", "DiaShaft/2*sin(360deg/SymmetryFactor)", "0mm"], - ["DiaShaft/2*cos(360deg/(2*SymmetryFactor))", "DiaShaft/2*sin(360deg/(2*SymmetryFactor))", "0mm"], - ["DiaShaft/2", "0mm", "0mm"], - ["DiaStatorGap/2-Airgap", "0mm", "0mm"], - ["(DiaStatorGap/2-Airgap)*cos(360deg/(2*SymmetryFactor))", "(DiaStatorGap/2-Airgap)*sin(360deg/(2*SymmetryFactor))", "0mm"], - ["(DiaStatorGap/2-Airgap)*cos(360deg/SymmetryFactor)", "(DiaStatorGap/2-Airgap)*sin(360deg/SymmetryFactor)", "0mm"], - ] - - def set_derived_params(self): - self.rotor_r_min = self.mm_to_str("geom_params", "DiaShaft") / 2 - self.rotor_r_max = self.mm_to_str("geom_params", "DiaStatorGap") / 2 - self.mm_to_str("geom_params", "Airgap") - - def set_udp_par_list_stator(self): - self.udp_par_list_stator = [ - ["DiaGap", "DiaStatorGap"], - ["DiaYoke", "DiaStatorYoke"], - ["Length", "0mm"], - ["Skew", "0deg"], - ["Slots", "SlotNumber"], - ["SlotType", "SlotType"], - ["Hs0", "Hs0"], - ["Hs01", "0mm"], - ["Hs1", "Hs1"], - ["Hs2", "Hs2"], - ["Bs0", "Bs0"], - ["Bs1", "Bs1"], - ["Bs2", "Bs2"], - ["Rs", "Rs"], - ["FilletType", "0"], - ["HalfSlot", "0"], - ["SegAngle", "0deg"], - ["LenRegion", "0mm"], - ["InfoCore", "0"], - ] +class Geometry(Geometry3f36s): def build_stator(self, m2d: Maxwell2d) -> None: - self._push_stator_variables(m2d) - shaft_id, region_id, band_id = self._build_vacuum_regions(m2d) - self._assign_rotor_motion(m2d) - stator_id = self._build_stator_core(m2d) - id_coils = self._build_stator_coils(m2d) - self._split_for_symmetry(m2d, [stator_id, shaft_id, region_id, band_id]) - self._assign_boundary_conditions(m2d) - self._assign_stator_mesh(m2d, stator_id, id_coils) + super().build_stator(m2d) self._create_material(m2d, self.magnet, **self.magnet_props) - # core loss - m2d.set_core_losses("Stator", core_loss_on_field=False) - - self.stator_id = stator_id - self.shaft_id = shaft_id - self.region_id = region_id - self.band_id = band_id - self.id_coils = id_coils - def _assign_rotor_motion(self, m2d: Maxwell2d) -> None: - m2d.assign_rotate_motion( - assignment="Band", - coordinate_system="Global", - axis="Z", - positive_movement=True, - start_position="InitPos", - angular_velocity="RotSpeed", - has_rotation_limits=False, - ) - - def _build_stator_core(self, m2d: Maxwell2d): - modeler = m2d.modeler - assert isinstance(modeler, Modeler2D) - - stator_id = modeler.create_udp( - dll="RMxprt/SlotCore.dll", - parameters=self.udp_par_list_stator, - library="syslib", - name="Stator", - # SolveInside="True", - ) - stator_id.material_name = self.Fe - - return stator_id - - def _build_stator_coils(self, m2d: Maxwell2d): - modeler = m2d.modeler - assert isinstance(modeler, Modeler2D) - - coil_id = modeler.create_rectangle( - origin=["DiaStatorGap/2+Hs0+Hs1+SlotLiner", "-(Bs1/2-SlotLiner)", 0], - sizes=["(Hs2+Rs/2-2*SlotLiner)/Layers-(Layers-1)*SpaceLayers/2", "Bs1-2*SlotLiner", 0], - name="Coil", - material="copper", - ) - modeler.rotate(assignment=coil_id, axis="Z", angle="360deg/SlotNumber/2") - coil_id.duplicate_around_axis(axis="Z", angle="360deg/SlotNumber", clones="SlotNumber/Poles", create_new_objects=True) - id_coils = modeler.get_objects_w_string(string_name="Coil", case_sensitive=True) - - return id_coils - - def _assign_stator_mesh(self, m2d: Maxwell2d, stator_id, id_coils) -> None: - m2d.mesh.assign_length_mesh( - assignment=id_coils, - inside_selection=True, - maximum_length=3, - maximum_elements=None, - name="coils", - ) - m2d.mesh.assign_length_mesh( - assignment=stator_id, - inside_selection=True, - maximum_length=3, - maximum_elements=None, - name="stator", - ) - - -class Computation(ComputationBase): - def set_oper_params(self): +class Computation(Computation3f36s): + def set_oper_params(self) -> None: f = 50 # [Hz] RotSpeed = 60 * f / self.geometry.PolePairs # [rpm] w = 2 * np.pi * f @@ -185,10 +30,10 @@ def set_oper_params(self): "PointPer": "101", # number of time points per period } - def set_solution_expressions(self): + def set_solution_expressions(self) -> None: self.solution_expressions = "Moving1.Torque" - def set_output_vars(self): + def set_output_vars(self) -> None: self.output_vars = { "pos": "(Moving1.Position -InitPos) * Poles/2", "cos0": "cos(pos)", @@ -214,57 +59,18 @@ def set_output_vars(self): "Irms": "sqrt(I_d^2+I_q^2)/sqrt(2)", } - def set_post_params(self): - self.post_params = { # reports - ("InducedVoltage(PhaseA)", "InducedVoltage(PhaseB)", "InducedVoltage(PhaseC)"): "InducedVoltage", - ("Moving1.Torque"): "Torque", - ("InputCurrent(PhaseA)", "InputCurrent(PhaseB)", "InputCurrent(PhaseC)"): "Current", - ( - "FluxLinkage(PhaseA)", - "FluxLinkage(PhaseB)", - "FluxLinkage(PhaseC)", - ): "FluxLinkage", - ("I_d", "I_q"): "Current_dq", - ("Flux_d", "Flux_q"): "FluxLinkage_dq", - ("Ui_d", "Ui_q"): "InducedVoltage_dq", - ("L_d", "L_q"): "Inductance_dq", - } - - def assign_stator_coils(self, m2d: Maxwell2d) -> None: - # Excitations - I_A = "Im * cos(w*Time+epsI)" - I_B = "Im * cos(w*Time-120deg+epsI)" - I_C = "Im * cos(w*Time-240deg+epsI)" - - phases_polarity = ["Positive", "Negative", "Positive"] - phases_name = ["A", "C", "B"] - phases_current = [I_A, I_C, I_B] - i_coil = 0 - for phase_polarity, phase_name, phase_current in zip(phases_polarity, phases_name, phases_current): - names = [] - for _ in range(3): - m2d.assign_coil( - assignment=[self.geometry.id_coils[i_coil]], - conductors_number="Nc", - polarity=phase_polarity, - name=f"CS{i_coil + 1}", - ) - names.append(f"CS{i_coil + 1}") - i_coil += 1 - m2d.assign_winding( - assignment=None, - winding_type="Current", - is_solid=False, - current=phase_current, - parallel_branches="ParallelPaths", - name=f"Phase{phase_name}", - ) - m2d.add_winding_coils(assignment=f"Phase{phase_name}", coils=names) - - def inductance_computation(self, m2d: Maxwell2d) -> None: - m2d.change_inductance_computation(compute_transient_inductance=True, incremental_matrix=False) + def set_post_params(self) -> None: + super().set_post_params() + self.post_params.update( + { + ("I_d", "I_q"): "Current_dq", + ("Flux_d", "Flux_q"): "FluxLinkage_dq", + ("Ui_d", "Ui_q"): "InducedVoltage_dq", + ("L_d", "L_q"): "Inductance_dq", + } + ) - def set_variables(self, m2d: Maxwell2d, *args): + def set_variables(self, m2d: Maxwell2d, *args) -> None: pass def extract_results(self, solutions): From b542d200b56054689c78b0d377de849329ec31b0 Mon Sep 17 00:00:00 2001 From: Polina Date: Thu, 8 Oct 2026 09:17:04 +0200 Subject: [PATCH 09/11] edits --- machine_design/designs/geometry.py | 6 ------ motors/synrm_3f_36s_mag.py | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/machine_design/designs/geometry.py b/machine_design/designs/geometry.py index b22d643..82f8dbb 100644 --- a/machine_design/designs/geometry.py +++ b/machine_design/designs/geometry.py @@ -10,7 +10,6 @@ class GeometryBase(ABC): def __init__(self) -> None: self.set_iron() - self.set_magnets() self.set_geom_params() self.set_slot_params() self.set_winds_params() @@ -229,7 +228,6 @@ def add_rotor_magnet(self, m2d: Maxwell2d, mag: np.ndarray, fill_height=0.9, fil cs_angle_deg = np.degrees(np.arctan2(radial[1], radial[0])) self.assign_magnet_cs(m2d, mag_id, cs_angle_deg) - self._create_material(m2d, self.magnet, **self.magnet_props) mag_id.material_name = self.magnet mag_id.solve_inside = True mag_id.color = (255, 0, 0) @@ -251,10 +249,6 @@ def assign_magnet_cs(self, m2d: Maxwell2d, magnet_name: str, angle_deg: float) - self._create_magnet_cs(m2d, cs_name, angle_deg) m2d.modeler[magnet_name].part_coordinate_system = cs_name - def set_magnets(self): - self.magnet = "NdFeb" - self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) - def _create_material( self, m2d: Maxwell2d, diff --git a/motors/synrm_3f_36s_mag.py b/motors/synrm_3f_36s_mag.py index 40bf47d..ade2a1a 100644 --- a/motors/synrm_3f_36s_mag.py +++ b/motors/synrm_3f_36s_mag.py @@ -14,6 +14,9 @@ def build_stator(self, m2d: Maxwell2d) -> None: super().build_stator(m2d) self._create_material(m2d, self.magnet, **self.magnet_props) + def set_magnets(self): + self.magnet = "NdFeb" + self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) class Computation(Computation3f36s): def set_oper_params(self) -> None: From 95cb405d54d839243ae1eb7873d204035699fdeb Mon Sep 17 00:00:00 2001 From: Polina Date: Thu, 8 Oct 2026 11:06:53 +0200 Subject: [PATCH 10/11] Update synrm_3f_36s_mag.py --- motors/synrm_3f_36s_mag.py | 62 ++------------------------------------ 1 file changed, 2 insertions(+), 60 deletions(-) diff --git a/motors/synrm_3f_36s_mag.py b/motors/synrm_3f_36s_mag.py index ade2a1a..2421eec 100644 --- a/motors/synrm_3f_36s_mag.py +++ b/motors/synrm_3f_36s_mag.py @@ -1,6 +1,5 @@ """Anchor `synrm_3f_36s`: 3-phase synchronous reluctance machine, 36 stator slots.""" -import numpy as np from ansys.aedt.core import Maxwell2d from motors.synrm_3f_36s import Computation as Computation3f36s @@ -18,63 +17,6 @@ def set_magnets(self): self.magnet = "NdFeb" self.magnet_props = dict(permeability=1.05, conductivity=0, density=7500, coercivity=900000, coercivity_dir=(1.0, 0.0, 0.0)) -class Computation(Computation3f36s): - def set_oper_params(self) -> None: - f = 50 # [Hz] - RotSpeed = 60 * f / self.geometry.PolePairs # [rpm] - w = 2 * np.pi * f - self.oper_params = { - "Im": "1.5*sqrt(2)A", - "epsI": "pi/4", # current angle - "InitPos": "-30deg", - "w": f"{w}Hz", - "RotSpeed": f"{RotSpeed}rpm", - "Nper": "1/6", # number of included periods - "PointPer": "101", # number of time points per period - } - - def set_solution_expressions(self) -> None: - self.solution_expressions = "Moving1.Torque" - - def set_output_vars(self) -> None: - self.output_vars = { - "pos": "(Moving1.Position -InitPos) * Poles/2", - "cos0": "cos(pos)", - "cos1": "cos(pos-2*PI/3)", - "cos2": "cos(pos-4*PI/3)", - "sin0": "sin(pos)", - "sin1": "sin(pos-2*PI/3)", - "sin2": "sin(pos-4*PI/3)", - "Lad": "L(PhaseA,PhaseA)*cos0 + L(PhaseA,PhaseB)*cos1 + L(PhaseA,PhaseC)*cos2", - "Laq": "L(PhaseA,PhaseA)*sin0 + L(PhaseA,PhaseB)*sin1 + L(PhaseA,PhaseC)*sin2", - "Lbd": "L(PhaseB,PhaseA)*cos0 + L(PhaseB,PhaseB)*cos1 + L(PhaseB,PhaseC)*cos2", - "Lbq": "L(PhaseB,PhaseA)*sin0 + L(PhaseB,PhaseB)*sin1 + L(PhaseB,PhaseC)*sin2", - "Lcd": "L(PhaseC,PhaseA)*cos0 + L(PhaseC,PhaseB)*cos1 + L(PhaseC,PhaseC)*cos2", - "Lcq": "L(PhaseC,PhaseA)*sin0 + L(PhaseC,PhaseB)*sin1 + L(PhaseC,PhaseC)*sin2", - "L_d": "(Lad*cos0 + Lbd*cos1 + Lcd*cos2) * 2/3", - "L_q": "(Laq*sin0 + Lbq*sin1 + Lcq*sin2) * 2/3", - "Flux_d": "(FluxLinkage(PhaseA)*cos0+FluxLinkage(PhaseB)*cos1+FluxLinkage(PhaseC)*cos2)*2/3", - "Flux_q": "-(FluxLinkage(PhaseA)*sin0+FluxLinkage(PhaseB)*sin1+FluxLinkage(PhaseC)*sin2)*2/3", - "Ui_d": "(InducedVoltage(PhaseA)*cos0+InducedVoltage(PhaseB)*cos1+InducedVoltage(PhaseC)*cos2)*2/3", - "Ui_q": "-(InducedVoltage(PhaseA)*sin0+InducedVoltage(PhaseB)*sin1+InducedVoltage(PhaseC)*sin2)*2/3", - "I_d": "(InputCurrent(PhaseA)*cos0 + InputCurrent(PhaseB)*cos1 + InputCurrent(PhaseC)*cos2)*2/3", - "I_q": "-(InputCurrent(PhaseA)*sin0 + InputCurrent(PhaseB)*sin1 + InputCurrent(PhaseC)*sin2)*2/3", - "Irms": "sqrt(I_d^2+I_q^2)/sqrt(2)", - } - def set_post_params(self) -> None: - super().set_post_params() - self.post_params.update( - { - ("I_d", "I_q"): "Current_dq", - ("Flux_d", "Flux_q"): "FluxLinkage_dq", - ("Ui_d", "Ui_q"): "InducedVoltage_dq", - ("L_d", "L_q"): "Inductance_dq", - } - ) - - def set_variables(self, m2d: Maxwell2d, *args) -> None: - pass - - def extract_results(self, solutions): - return solutions.data_magnitude() +class Computation(Computation3f36s): + pass From b0d888d08aec576f7ac01c1ce7c2837375b4dc8c Mon Sep 17 00:00:00 2001 From: Polina Date: Thu, 8 Oct 2026 11:31:43 +0200 Subject: [PATCH 11/11] Update synrm_3f_36s_mag.py --- motors/synrm_3f_36s_mag.py | 1 + 1 file changed, 1 insertion(+) diff --git a/motors/synrm_3f_36s_mag.py b/motors/synrm_3f_36s_mag.py index 2421eec..808ece2 100644 --- a/motors/synrm_3f_36s_mag.py +++ b/motors/synrm_3f_36s_mag.py @@ -11,6 +11,7 @@ class Geometry(Geometry3f36s): def build_stator(self, m2d: Maxwell2d) -> None: super().build_stator(m2d) + self.set_magnets() self._create_material(m2d, self.magnet, **self.magnet_props) def set_magnets(self):