From 588263d68f8d7d5e276e351ed4e24b4390ccc8e9 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 08:00:42 +0200 Subject: [PATCH 01/11] modify solution_expressions --- motors/synrm_3f_36s.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index dd3a840..d4cb066 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -6,6 +6,7 @@ from machine_design.designs.computation import ComputationBase from machine_design.designs.geometry import GeometryBase +from machine_design.generic.transforms import to_dq class Geometry(GeometryBase): @@ -174,12 +175,13 @@ def set_oper_params(self): f = 50 # [Hz] RotSpeed = 60 * f / self.geometry.PolePairs # [rpm] w = 2 * np.pi * f + self.InitPos = -30 # deg self.oper_params = { "Id": "0.0A", "Iq": "0.0A", "epsI": "atan2(Iq,Id)", # current angle "Im": "sqrt(Id^2+Iq^2)", - "InitPos": "-30deg", + "InitPos": f"{self.InitPos}deg", "w": f"{w}Hz", "RotSpeed": f"{RotSpeed}rpm", "Nper": "1/6", # number of included periods @@ -187,7 +189,14 @@ def set_oper_params(self): } def set_solution_expressions(self): - self.solution_expressions = "Moving1.Torque" + self.solution_expressions = [ + "Moving1.Position", + "Moving1.Torque", + *[f"FluxLinkage(Phase{p})" for p in "ABC"], + *[f"InducedVoltage(Phase{p})" for p in "ABC"], + *[f"InputCurrent(Phase{p})" for p in "ABC"], + *[f"L(Phase{x},Phase{y})" for x in "ABC" for y in "ABC"], + ] def set_output_vars(self): self.output_vars = { From 4c54adc67c76536f530489580b49014ed5ed3f69 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 09:26:31 +0200 Subject: [PATCH 02/11] move vars to extract_results() --- motors/synrm_3f_36s.py | 69 +++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index d4cb066..adc6163 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -199,30 +199,7 @@ def set_solution_expressions(self): ] 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)", - } + self.output_vars = {} def set_post_params(self): self.post_params = { # reports @@ -275,8 +252,50 @@ def inductance_computation(self, m2d: Maxwell2d) -> None: m2d.change_inductance_computation(compute_transient_inductance=True, incremental_matrix=False) def set_variables(self, m2d: Maxwell2d, Id, Iq): + self.Id, self.Iq = Id, Iq m2d.variable_manager["Id"] = f"{Id}A" m2d.variable_manager["Iq"] = f"{Iq}A" def extract_results(self, solutions): - return solutions.data_magnitude() + position = np.array(solutions.data_real("Moving1.Position")) + torque = np.array(solutions.data_real("Moving1.Torque")) + + theta_el = np.deg2rad(position-self.InitPos)*self.geometry.PolePairs + flux_phases = np.stack([np.array(solutions.data_real(f"FluxLinkage(Phase{p})")) for p in "ABC"], axis=-1) + vind_phases = np.stack([np.array(solutions.data_real(f"InducedVoltage(Phase{p})")) for p in "ABC"], axis=-1) + current_phases = np.stack([np.array(solutions.data_real(f"InputCurrent(Phase{p})")) for p in "ABC"], axis=-1) + + Flux_d, Flux_q = to_dq(flux_phases, theta_el, harmonic=1) + Ui_d, Ui_q = to_dq(vind_phases, theta_el, harmonic=1) + I_d, I_q = (v / 1e3 for v in to_dq(current_phases, theta_el, harmonic=1)) + # mA to A + + L_raw = [np.stack([np.array(solutions.data_real(f"L(Phase{x},Phase{y})")) for y in "ABC"], axis=-1) / 1e9 for x in "ABC"] + # nH to H + + L_d_row = np.zeros((len(position), 3)) + L_q_row = np.zeros((len(position), 3)) + for i, L_row in enumerate(L_raw): + L_d_row[:, i], L_q_row[:, i] = (v*m for v, m in zip(to_dq(L_row, theta_el, harmonic=1), (3/2, -3/2))) + + L_d, _ = to_dq(L_d_row, theta_el, harmonic=1) + _, L_q_raw = to_dq(L_q_row, theta_el, harmonic=1) + L_q = -L_q_raw + + Irms=np.sqrt(I_d**2+I_q**2)/np.sqrt(2) + + + out = { + "Flux_d": Flux_d, + "Flux_q": Flux_q, + "Ui_d": Ui_d, + "Ui_q": Ui_q, + "I_d": I_d, + "I_q": I_q, + "L_d": L_d, + "L_q": L_q, + "Irms": Irms, + "Moving1.Torque": torque, + } + + return out From bac19c5d496ef61db81c69e72d12ef68ed5e34cc Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 09:30:56 +0200 Subject: [PATCH 03/11] ruff format --- motors/synrm_3f_36s.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/motors/synrm_3f_36s.py b/motors/synrm_3f_36s.py index adc6163..93af0c0 100644 --- a/motors/synrm_3f_36s.py +++ b/motors/synrm_3f_36s.py @@ -260,7 +260,7 @@ def extract_results(self, solutions): position = np.array(solutions.data_real("Moving1.Position")) torque = np.array(solutions.data_real("Moving1.Torque")) - theta_el = np.deg2rad(position-self.InitPos)*self.geometry.PolePairs + theta_el = np.deg2rad(position - self.InitPos) * self.geometry.PolePairs flux_phases = np.stack([np.array(solutions.data_real(f"FluxLinkage(Phase{p})")) for p in "ABC"], axis=-1) vind_phases = np.stack([np.array(solutions.data_real(f"InducedVoltage(Phase{p})")) for p in "ABC"], axis=-1) current_phases = np.stack([np.array(solutions.data_real(f"InputCurrent(Phase{p})")) for p in "ABC"], axis=-1) @@ -276,14 +276,13 @@ def extract_results(self, solutions): L_d_row = np.zeros((len(position), 3)) L_q_row = np.zeros((len(position), 3)) for i, L_row in enumerate(L_raw): - L_d_row[:, i], L_q_row[:, i] = (v*m for v, m in zip(to_dq(L_row, theta_el, harmonic=1), (3/2, -3/2))) + L_d_row[:, i], L_q_row[:, i] = (v * m for v, m in zip(to_dq(L_row, theta_el, harmonic=1), (3 / 2, -3 / 2))) L_d, _ = to_dq(L_d_row, theta_el, harmonic=1) _, L_q_raw = to_dq(L_q_row, theta_el, harmonic=1) L_q = -L_q_raw - Irms=np.sqrt(I_d**2+I_q**2)/np.sqrt(2) - + Irms = np.sqrt(I_d**2 + I_q**2) / np.sqrt(2) out = { "Flux_d": Flux_d, From 1fb5fa9ee1212f5caff74264c7899a89b7402d26 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 10:48:11 +0200 Subject: [PATCH 04/11] update test file according to new code and test_synrm_5f_40s.py --- tests/test_synrm_3f_36s.py | 46 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/tests/test_synrm_3f_36s.py b/tests/test_synrm_3f_36s.py index a05fa99..5e1604c 100644 --- a/tests/test_synrm_3f_36s.py +++ b/tests/test_synrm_3f_36s.py @@ -1,9 +1,9 @@ -import re from types import SimpleNamespace import numpy as np import pytest +from machine_design.generic.transforms import to_dq from motors.synrm_3f_36s import Computation, Geometry @@ -95,8 +95,12 @@ def test_derived_params(geometry): assert geometry.rotor_r_max == pytest.approx(39.5 - 0.225) -def test_solution_expressions(computation): - assert computation.solution_expressions == "Moving1.Torque" +def test_solution_expressions_is_a_list_ending_in_torque(computation): + assert isinstance(computation.solution_expressions, list) + assert computation.solution_expressions[0] == "Moving1.Position" + assert computation.solution_expressions[1] == "Moving1.Torque" + assert computation.solution_expressions[-1] == "L(PhaseC,PhaseC)" + assert len(computation.solution_expressions) == 20 def test_udp_par_list_stator(geometry): @@ -124,20 +128,8 @@ def test_udp_par_list_stator(geometry): ] -def test_output_vars_only_reference_earlier_keys(computation): - # Ansys evaluates output variables in insertion order, so a formula referencing - # another output variable must not reference one that is defined later. - defined = set() - all_keys = set(computation.output_vars.keys()) - for key, formula in computation.output_vars.items(): - later_keys = all_keys - defined - {key} - referenced_later = [k for k in later_keys if re.search(rf"\b{re.escape(k)}\b", formula)] - assert not referenced_later, f"'{key}' formula references not-yet-defined {referenced_later}" - defined.add(key) - - -def test_output_vars_known_formula(computation): - assert computation.output_vars["Irms"] == "sqrt(I_d^2+I_q^2)/sqrt(2)" +def test_output_vars_is_empty(computation): + assert computation.output_vars == {} def test_post_params_plot_names_unique(computation): @@ -154,6 +146,20 @@ def test_mm_to_str_raises_without_mm_suffix(geometry): geometry.mm_to_str("geom_params", "SlotNumber") -def test_extract_results_returns_data_magnitude(computation): - solutions = SimpleNamespace(data_magnitude=lambda: [1.0, 2.0, 3.0]) - assert computation.extract_results(solutions) == [1.0, 2.0, 3.0] +def test_extract_results_converts_units(computation): + computation.set_variables(SimpleNamespace(variable_manager={}), Id=1.0, Iq=2.0) + + def data_real(expr): + letters = ["ABC".index(part[0]) + 1 for part in expr.split("Phase")[1:]] + value = float(np.prod(letters) if letters else 7.0) + return np.full(2, value * 1e9 if expr.startswith("L(") else value) + + solutions = SimpleNamespace(data_real=data_real, primary_sweep_values=[0.0, 1.0]) + out = computation.extract_results(solutions) + + theta_el = np.deg2rad(np.full(2, 7.0)-computation.InitPos)*computation.geometry.PolePairs + current_phases = np.stack([np.full(2, i + 1.0) for i in range(3)], axis=-1) + expected_I_d, _ = to_dq(current_phases, theta_el, harmonic=1) + + assert out["I_d"] == pytest.approx(expected_I_d / 1e3) + assert out["Moving1.Torque"] == pytest.approx(np.full(2, 7.0)) From 5e588445be4fd54de30d5d7fa6532f8e8115d623 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 11:47:40 +0200 Subject: [PATCH 05/11] very processing vars --- tests/test_ansys_regression.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index e910202..da22d9a 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -30,6 +30,17 @@ SEEDS = (42, 43) NUM_CORES = 1 current_setpoint = (1.5, 1.5) +check_expressions=[ + "Flux_d", + "Flux_q", + "Ui_d", + "Ui_q", + "I_d", + "I_q", + "L_d", + "L_q", + "Irms", +] def _load_legacy_design_class(): @@ -102,11 +113,15 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): for seed, barriers in zip(SEEDS, barrier_sets): torque_legacy = _compute_torque(legacy_design, barriers, _add_rotor) + solutions=legacy_design.m2d.post.get_solution_data(expressions=check_expressions, primary_sweep_variable="Time") + check_legacy={expr: np.array(solutions.data_real(expr)) for expr in check_expressions} torque_live = _compute_torque(live_design, barriers, _add_rotor) assert torque_legacy is not None, f"legacy torque is None for seed {seed}" assert torque_live is not None, f"live torque is None for seed {seed}" - np.testing.assert_allclose(torque_live, torque_legacy, rtol=1e-6, err_msg=f"mismatch for seed {seed}") + for expr in check_expressions: + np.testing.assert_allclose(torque_live[expr], check_legacy[expr], rtol=1e-3, err_msg=f"mismatch for {expr}, seed {seed}") + np.testing.assert_allclose(torque_live["Moving1.Torque"], torque_legacy, rtol=1e-3, err_msg=f"mismatch for Moving1.Torque, seed {seed}") finally: if live_design is not None: live_design.close_project() From ba4c6fd3e5c25b99d2140a1d455ce177793cc78f Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 11:57:57 +0200 Subject: [PATCH 06/11] update _compute_torque() --- tests/test_ansys_regression.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index da22d9a..4b333c4 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -87,11 +87,15 @@ def _create_design(design_cls, project_name, file_name, extra_args=()): ) -def _compute_torque(design, barriers, add_rotor, setpoint=current_setpoint): +def _compute_torque(design, barriers, add_rotor, setpoint=current_setpoint, check_expressions=None): add_rotor(design, barriers) torque = design.compute(*setpoint, NUM_CORES=NUM_CORES) + check=None + if check_expressions is not None: + solutions=design.m2d.post.get_solution_data(expressions=check_expressions, primary_sweep_variable="Time") + check={expr: np.array(solutions.data_real(expr)) for expr in check_expressions} design.delete_rotor() - return torque + return (torque, check) if check_expressions is not None else torque def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): @@ -112,9 +116,7 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): ) for seed, barriers in zip(SEEDS, barrier_sets): - torque_legacy = _compute_torque(legacy_design, barriers, _add_rotor) - solutions=legacy_design.m2d.post.get_solution_data(expressions=check_expressions, primary_sweep_variable="Time") - check_legacy={expr: np.array(solutions.data_real(expr)) for expr in check_expressions} + torque_legacy, check_legacy = _compute_torque(legacy_design, barriers, _add_rotor, check_expressions=check_expressions) torque_live = _compute_torque(live_design, barriers, _add_rotor) assert torque_legacy is not None, f"legacy torque is None for seed {seed}" From e1b47f0f7105b2b4073bd328868272ced7c0c1e5 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 12:01:05 +0200 Subject: [PATCH 07/11] ruff format --- tests/test_ansys_regression.py | 10 +++++----- tests/test_synrm_3f_36s.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index 4b333c4..56172f2 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -30,7 +30,7 @@ SEEDS = (42, 43) NUM_CORES = 1 current_setpoint = (1.5, 1.5) -check_expressions=[ +check_expressions = [ "Flux_d", "Flux_q", "Ui_d", @@ -90,10 +90,10 @@ def _create_design(design_cls, project_name, file_name, extra_args=()): def _compute_torque(design, barriers, add_rotor, setpoint=current_setpoint, check_expressions=None): add_rotor(design, barriers) torque = design.compute(*setpoint, NUM_CORES=NUM_CORES) - check=None + check = None if check_expressions is not None: - solutions=design.m2d.post.get_solution_data(expressions=check_expressions, primary_sweep_variable="Time") - check={expr: np.array(solutions.data_real(expr)) for expr in check_expressions} + solutions = design.m2d.post.get_solution_data(expressions=check_expressions, primary_sweep_variable="Time") + check = {expr: np.array(solutions.data_real(expr)) for expr in check_expressions} design.delete_rotor() return (torque, check) if check_expressions is not None else torque @@ -123,7 +123,7 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): assert torque_live is not None, f"live torque is None for seed {seed}" for expr in check_expressions: np.testing.assert_allclose(torque_live[expr], check_legacy[expr], rtol=1e-3, err_msg=f"mismatch for {expr}, seed {seed}") - np.testing.assert_allclose(torque_live["Moving1.Torque"], torque_legacy, rtol=1e-3, err_msg=f"mismatch for Moving1.Torque, seed {seed}") + np.testing.assert_allclose(torque_live["Moving1.Torque"], torque_legacy, rtol=1e-3, err_msg=f"mismatch for Moving1.Torque, seed {seed}") finally: if live_design is not None: live_design.close_project() diff --git a/tests/test_synrm_3f_36s.py b/tests/test_synrm_3f_36s.py index 5e1604c..3f5fa68 100644 --- a/tests/test_synrm_3f_36s.py +++ b/tests/test_synrm_3f_36s.py @@ -157,7 +157,7 @@ def data_real(expr): solutions = SimpleNamespace(data_real=data_real, primary_sweep_values=[0.0, 1.0]) out = computation.extract_results(solutions) - theta_el = np.deg2rad(np.full(2, 7.0)-computation.InitPos)*computation.geometry.PolePairs + theta_el = np.deg2rad(np.full(2, 7.0) - computation.InitPos) * computation.geometry.PolePairs current_phases = np.stack([np.full(2, i + 1.0) for i in range(3)], axis=-1) expected_I_d, _ = to_dq(current_phases, theta_el, harmonic=1) From 2e5d8e1eb12340ac29cb0b535a3d3abd4733564c Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 12:13:23 +0200 Subject: [PATCH 08/11] simplify taking vars process --- tests/test_ansys_regression.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index 56172f2..d137c40 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -87,15 +87,11 @@ def _create_design(design_cls, project_name, file_name, extra_args=()): ) -def _compute_torque(design, barriers, add_rotor, setpoint=current_setpoint, check_expressions=None): +def _compute_torque(design, barriers, add_rotor, setpoint=current_setpoint): add_rotor(design, barriers) torque = design.compute(*setpoint, NUM_CORES=NUM_CORES) - check = None - if check_expressions is not None: - solutions = design.m2d.post.get_solution_data(expressions=check_expressions, primary_sweep_variable="Time") - check = {expr: np.array(solutions.data_real(expr)) for expr in check_expressions} design.delete_rotor() - return (torque, check) if check_expressions is not None else torque + return torque def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): @@ -105,6 +101,7 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): legacy_design, live_design = None, None try: legacy_design = _create_design(LegacyDesign, "RegressionTest_legacy", str(tmp_path / "legacy.aedt")) + legacy_design.solution_expressions=["Moving1.Torque", *check_expressions] live_geometry = Geometry() live_computation = Computation(live_geometry) @@ -116,14 +113,15 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): ) for seed, barriers in zip(SEEDS, barrier_sets): - torque_legacy, check_legacy = _compute_torque(legacy_design, barriers, _add_rotor, check_expressions=check_expressions) + torque_legacy = _compute_torque(legacy_design, barriers, _add_rotor) torque_live = _compute_torque(live_design, barriers, _add_rotor) assert torque_legacy is not None, f"legacy torque is None for seed {seed}" assert torque_live is not None, f"live torque is None for seed {seed}" - for expr in check_expressions: - np.testing.assert_allclose(torque_live[expr], check_legacy[expr], rtol=1e-3, err_msg=f"mismatch for {expr}, seed {seed}") np.testing.assert_allclose(torque_live["Moving1.Torque"], torque_legacy, rtol=1e-3, err_msg=f"mismatch for Moving1.Torque, seed {seed}") + for expr in check_expressions: + np.testing.assert_allclose(torque_live[expr], torque_legacy[expr], rtol=1e-3, err_msg=f"mismatch for {expr}, seed {seed}") + finally: if live_design is not None: live_design.close_project() From c9b1534aa57b48186f449e7e7711e9a3e5536572 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 12:43:00 +0200 Subject: [PATCH 09/11] very magnitudes of units --- tests/test_ansys_regression.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index d137c40..484682e 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -101,7 +101,20 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): legacy_design, live_design = None, None try: legacy_design = _create_design(LegacyDesign, "RegressionTest_legacy", str(tmp_path / "legacy.aedt")) - legacy_design.solution_expressions=["Moving1.Torque", *check_expressions] + legacy_design.solution_expressions = ["Moving1.Torque", *check_expressions] + + def _legacy_extract_results(solutions): + out = {} + for expr in legacy_design.solution_expressions: + val = np.array(solutions.data_real(expr)) + if expr in ("I_d", "I_q"): + val = val / 1e3 + elif expr in ("L_d", "L_q"): + val = val / 1e9 + out[expr] = val + return out + + legacy_design.extract_results = _legacy_extract_results live_geometry = Geometry() live_computation = Computation(live_geometry) @@ -118,10 +131,10 @@ def test_legacy_and_live_design_match_across_rotor_rebuilds(tmp_path): assert torque_legacy is not None, f"legacy torque is None for seed {seed}" assert torque_live is not None, f"live torque is None for seed {seed}" - np.testing.assert_allclose(torque_live["Moving1.Torque"], torque_legacy, rtol=1e-3, err_msg=f"mismatch for Moving1.Torque, seed {seed}") + np.testing.assert_allclose(torque_live["Moving1.Torque"], torque_legacy["Moving1.Torque"], rtol=1e-3, err_msg=f"mismatch for Moving1.Torque, seed {seed}") for expr in check_expressions: np.testing.assert_allclose(torque_live[expr], torque_legacy[expr], rtol=1e-3, err_msg=f"mismatch for {expr}, seed {seed}") - + finally: if live_design is not None: live_design.close_project() From a6853daaff420fbc29b586f5cef05ef47d7ed31f Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 12:52:09 +0200 Subject: [PATCH 10/11] add explaination of check_expressions --- tests/test_ansys_regression.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index 484682e..89834e7 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -41,6 +41,7 @@ "L_q", "Irms", ] +# we should very all the above 9 vars + Moving1.Torque (a total of 10 vars with different seeds) def _load_legacy_design_class(): From 65f32deafb35a1143c1c108b324cb49c85356b84 Mon Sep 17 00:00:00 2001 From: haitao-ZCU Date: Thu, 24 Sep 2026 12:59:01 +0200 Subject: [PATCH 11/11] update --- tests/test_ansys_regression.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_ansys_regression.py b/tests/test_ansys_regression.py index 89834e7..5bf8111 100644 --- a/tests/test_ansys_regression.py +++ b/tests/test_ansys_regression.py @@ -41,7 +41,7 @@ "L_q", "Irms", ] -# we should very all the above 9 vars + Moving1.Torque (a total of 10 vars with different seeds) +# we should verify all the above 9 vars + Moving1.Torque (a total of 10 vars with different seeds) def _load_legacy_design_class(): @@ -109,9 +109,9 @@ def _legacy_extract_results(solutions): for expr in legacy_design.solution_expressions: val = np.array(solutions.data_real(expr)) if expr in ("I_d", "I_q"): - val = val / 1e3 + val = val / 1e3 # mA to A elif expr in ("L_d", "L_q"): - val = val / 1e9 + val = val / 1e9 # nH to H out[expr] = val return out