axial_compare.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # -*- coding: utf-8 -*-
  2. """
  3. 对标 V3.0 解析报告的 FEA 验证扫描
  4. ==================================
  5. 参照《轴向磁通电机轴向磁拉力计算与轴承选型校核报告V3.0-20260826.pdf》:
  6. - 其基准: 磁钢 20°C, 空载 Fz=483 N (中值口径 500 N)
  7. - 其表3-3: g=0.6/1.0/1.5 mm -> 601/483/378 N, kneg(1mm)=250 N/mm
  8. 本模型 .mot 磁钢温度默认 100°C (Br -0.12%/K), 首先归一到 20°C 再扫气隙。
  9. 工况: 磁钢 20°C x 气隙 {0.6, 1.0, 1.5} mm, 各求解一次, 读 OC/OL 净轴向力
  10. 及气隙磁密; 有限差分求磁负刚度 kneg。
  11. 用法: python axial_compare.py [--quit]
  12. """
  13. import json
  14. import os
  15. import sys
  16. import time
  17. BASE = os.path.dirname(os.path.abspath(__file__))
  18. MOT_SRC = os.path.join(BASE, "MARS-12S10P_SSSR_D76-C150_V5.0-0819.mot")
  19. OUT_DIR = os.path.join(BASE, "output_motorcad")
  20. GAPS = [0.6, 1.0, 1.5]
  21. MAGNET_TEMP_C = 20.0
  22. MAX_TSTEPS = 64
  23. MAX_NODES = 40
  24. def stats(ys):
  25. if not ys:
  26. return None
  27. return {"mean": sum(ys) / len(ys), "min": min(ys), "max": max(ys),
  28. "pk2pk": max(ys) - min(ys), "n": len(ys)}
  29. def read_nodes(mc, graph, sec, tstep):
  30. xs, ys = [], []
  31. for i in range(MAX_NODES):
  32. try:
  33. x, y = mc.get_magnetic_3d_graph_point(graph, sec, i, tstep)
  34. except Exception:
  35. break
  36. xs.append(x)
  37. ys.append(y)
  38. return xs, ys
  39. def net_force_series(mc, graph):
  40. series = []
  41. for tstep in range(MAX_TSTEPS):
  42. total, got = 0.0, False
  43. for sec in (1, 2):
  44. xs, ys = read_nodes(mc, graph, sec, tstep)
  45. if not ys:
  46. continue
  47. got = True
  48. nu = len(ys) - 1 if (len(xs) > 1 and
  49. abs(xs[-1] - xs[0] - 360.0) < 1e-6) else len(ys)
  50. total += sum(ys[:nu])
  51. if not got:
  52. break
  53. series.append(total)
  54. return series
  55. def read_2d(mc, graph, maxpts=64):
  56. ys = []
  57. for i in range(maxpts):
  58. try:
  59. _, y = mc.get_magnetic_graph_point(graph, i)
  60. except Exception:
  61. break
  62. ys.append(y)
  63. return ys
  64. def main(argv):
  65. quit_after = "--quit" in argv
  66. os.makedirs(OUT_DIR, exist_ok=True)
  67. ts = time.strftime("%m%d_%H%M%S")
  68. from ansys.motorcad.core import MotorCAD
  69. print("启动 Motor-CAD (前台) ...")
  70. mc = MotorCAD()
  71. try:
  72. mc.set_visible(True) # /SCRIPTING 模式部分机器窗口不显示, 强制可见
  73. except Exception:
  74. pass
  75. results = {"when": ts, "magnet_temp_C": MAGNET_TEMP_C,
  76. "reference": "V3.0 报告表3-1/3-3: 20°C, g=0.6/1.0/1.5 -> "
  77. "601/483/378 N, kneg(1mm)=250 N/mm",
  78. "cases": []}
  79. try:
  80. mc.load_from_file(MOT_SRC)
  81. out_mot = os.path.join(OUT_DIR, "MARS_SSSR_compare_%s.mot" % ts)
  82. mc.save_to_file(out_mot)
  83. results["work_mot"] = out_mot
  84. t_before = mc.get_variable("Magnet_Temperature")
  85. results["magnet_temp_before_C"] = t_before
  86. mc.set_variable("Magnet_Temperature", MAGNET_TEMP_C)
  87. print("磁钢温度: %s -> %s °C" % (t_before, MAGNET_TEMP_C))
  88. for var in ["ElectromagneticForcesCalc_Load",
  89. "ElectromagneticForcesCalc_OC"]:
  90. mc.set_variable(var, True)
  91. for g in GAPS:
  92. mc.set_variable("Airgap", g)
  93. back = mc.get_variable("Airgap")
  94. print("== 气隙 %.1f mm (回读 %s), 求解 ..." % (g, back))
  95. t0 = time.time()
  96. mc.do_magnetic_calculation()
  97. dt = time.time() - t0
  98. case = {"airgap_mm": back, "solve_seconds": dt}
  99. for graph, key in [("Fr_Rotor_OC_Lumped", "F_OC"),
  100. ("Fr_Rotor_OL_Lumped", "F_OL")]:
  101. s = net_force_series(mc, graph)
  102. case[key] = stats(s)
  103. bys = read_2d(mc, "FluxDensityAirgap")
  104. if bys:
  105. case["B2_mean_T2"] = sum(b * b for b in bys) / len(bys)
  106. print(" F_OC=%.1f N, F_OL=%.1f N, mean(B²)=%.3f (耗时 %.0fs)"
  107. % (case["F_OC"]["mean"], case["F_OL"]["mean"],
  108. case.get("B2_mean_T2", -1), dt))
  109. results["cases"].append(case)
  110. # ---- 磁负刚度 (有限差分, OC 口径) ----
  111. cs = results["cases"]
  112. if len(cs) == 3:
  113. f = [c["F_OC"]["mean"] for c in cs]
  114. g0, g1, g2 = [c["airgap_mm"] for c in cs]
  115. k_low = -(f[1] - f[0]) / (g1 - g0) # 0.6~1.0 段
  116. k_high = -(f[2] - f[1]) / (g2 - g1) # 1.0~1.5 段
  117. k_mid = -(f[2] - f[0]) / (g2 - g0) # 全段中心差分
  118. results["kneg_N_per_mm"] = {"seg_0.6_1.0": k_low,
  119. "seg_1.0_1.5": k_high,
  120. "central_at_1.0": k_mid}
  121. print("kneg: 0.6~1.0段 %.0f, 1.0~1.5段 %.0f, 中心差分 %.0f N/mm "
  122. "(报告解析值 250)" % (k_low, k_high, k_mid))
  123. res_path = os.path.join(OUT_DIR, "compare_results_%s.json" % ts)
  124. with open(res_path, "w", encoding="utf-8") as fjson:
  125. json.dump(results, fjson, ensure_ascii=False, indent=2)
  126. print("RESULTS: %s" % res_path)
  127. return 0
  128. finally:
  129. if quit_after:
  130. try:
  131. mc.quit()
  132. except Exception:
  133. pass
  134. else:
  135. print("[提示] Motor-CAD 保持前台打开供检查。")
  136. if __name__ == "__main__":
  137. sys.exit(main(sys.argv[1:]))