axial_probe4.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. # -*- coding: utf-8 -*-
  2. """
  3. 第5轮: 力开关打开后筛 2D/3D 图名
  4. =================================
  5. 修正第3轮漏洞: 图名可能在 ElectromagneticForcesCalc_* 打开后才注册, 先开
  6. 开关再筛。同时筛 3D 力图 (get_magnetic_3d_graph_point, 空间x时间), 并用
  7. 已知图 (转矩/气隙磁密) 反推 Graph Viewer 命名惯例。
  8. 用法: python axial_probe4.py [--quit]
  9. """
  10. import json
  11. import os
  12. import sys
  13. import time
  14. BASE = os.path.dirname(os.path.abspath(__file__))
  15. MOT_SRC = os.path.join(BASE, "MARS-12S10P_SSSR_D76-C150_V5.0-0819.mot")
  16. OUT_DIR = os.path.join(BASE, "output_motorcad")
  17. # 已知图命名惯例侦察 (id17=转矩0.522, id0-2=相电流, FluxDensityAirgap 已知)
  18. KNOWN_PROBE = ["Torque", "Torque OL", "Torque (OL)", "TorqueOL", "Torque_OL",
  19. "Torque vs Angle", "TorqueVsAngle", "Cogging Torque",
  20. "Cogging Torque OC", "CoggingTorque", "Phase Current",
  21. "Phase Current OL", "Current", "CurrentOL", "Back EMF",
  22. "Phase EMF", "FluxDensityAirgap", "Airgap Flux Density"]
  23. BASES = ["Axial Force", "Axial_Force", "AxialForce", "Fz", "Fa"]
  24. ENTS = ["", " Rotor", " Stator", "_Rotor", "_Stator", "Rotor", "Stator"]
  25. CASES = ["", " OL", " OC", "_OL", "_OC", " (OL)", " (OC)", " Load",
  26. " Open Circuit", "_OL_Lumped", "_OC_Lumped", "_Lumped"]
  27. D3_EXTRA = ["Ft_Rotor_OL_Lumped", "Fr_Rotor_OL_Lumped",
  28. "Ft_Stator_OL_Lumped", "Fr_Stator_OL_Lumped",
  29. "OL_Axial_Force_Rotor", "OC_Axial_Force_Rotor",
  30. "OL_Axial_Force_Stator", "OC_Axial_Force_Stator",
  31. "Load_Axial_Force_Rotor", "Load_Axial_Force_Stator"]
  32. def build_force_names():
  33. out = []
  34. for b in BASES:
  35. for e in ENTS:
  36. for c in CASES:
  37. n = b + e + c
  38. if n not in out:
  39. out.append(n)
  40. for n in D3_EXTRA:
  41. if n not in out:
  42. out.append(n)
  43. return out
  44. def classify2d(mc, g):
  45. try:
  46. mc.get_magnetic_graph_point(g, 0)
  47. return "OK"
  48. except Exception as e:
  49. m = str(e)
  50. if "does not exist" in m:
  51. return "ABSENT"
  52. if "No points exist" in m:
  53. return "EXISTS"
  54. return "ODD:" + m
  55. def classify3d(mc, g):
  56. try:
  57. mc.get_magnetic_3d_graph_point(g, 1, 0, 0)
  58. return "OK"
  59. except Exception as e:
  60. m = str(e)
  61. if "does not exist" in m:
  62. return "ABSENT"
  63. if "No points exist" in m or "no points" in m.lower():
  64. return "EXISTS"
  65. return "ODD:" + m
  66. def stats(ys):
  67. if not ys:
  68. return None
  69. return {"mean": sum(ys) / len(ys), "min": min(ys), "max": max(ys),
  70. "pk2pk": max(ys) - min(ys), "n": len(ys)}
  71. def read2d(mc, g, maxpts=128):
  72. xs, ys = [], []
  73. for i in range(maxpts):
  74. try:
  75. x, y = mc.get_magnetic_graph_point(g, i)
  76. except Exception:
  77. break
  78. xs.append(x)
  79. ys.append(y)
  80. return xs, ys
  81. def read3d(mc, g, section, maxpts=256, tstep=0):
  82. xs, ys = [], []
  83. for i in range(maxpts):
  84. try:
  85. x, y = mc.get_magnetic_3d_graph_point(g, section, i, tstep)
  86. except Exception:
  87. break
  88. xs.append(x)
  89. ys.append(y)
  90. return xs, ys
  91. def main(argv):
  92. quit_after = "--quit" in argv
  93. os.makedirs(OUT_DIR, exist_ok=True)
  94. ts = time.strftime("%m%d_%H%M%S")
  95. from ansys.motorcad.core import MotorCAD
  96. print("启动 Motor-CAD (前台) ...")
  97. mc = MotorCAD()
  98. results = {"when": ts, "probe_round": 5}
  99. try:
  100. mc.load_from_file(MOT_SRC)
  101. for var in ["ElectromagneticForcesCalc_Load",
  102. "ElectromagneticForcesCalc_OC"]:
  103. mc.set_variable(var, True)
  104. print("力开关已开, 开始筛名 (无求解) ...")
  105. known = {n: classify2d(mc, n) for n in KNOWN_PROBE}
  106. results["known_probe"] = known
  107. print("已知图命名侦察: %s" % json.dumps(
  108. {k: v for k, v in known.items() if v != "ABSENT"},
  109. ensure_ascii=False))
  110. force_names = build_force_names()
  111. hits2d = {}
  112. for n in force_names:
  113. k = classify2d(mc, n)
  114. if k != "ABSENT":
  115. hits2d[n] = k
  116. results["force_2d_hits"] = hits2d
  117. print("2D 力图命中: %s" % json.dumps(hits2d, ensure_ascii=False))
  118. hits3d = {}
  119. for n in force_names:
  120. k = classify3d(mc, n)
  121. if k != "ABSENT":
  122. hits3d[n] = k
  123. results["force_3d_hits"] = hits3d
  124. print("3D 力图命中: %s" % json.dumps(hits3d, ensure_ascii=False))
  125. promising2d = [n for n, k in hits2d.items()]
  126. promising3d = [n for n, k in hits3d.items()]
  127. if promising2d or promising3d:
  128. print("求解一次后读波形 ...")
  129. t0 = time.time()
  130. mc.do_magnetic_calculation()
  131. print(" 耗时 %.1f s" % (time.time() - t0))
  132. waves = {}
  133. for n in promising2d:
  134. xs, ys = read2d(mc, n)
  135. if ys:
  136. waves["2D:" + n] = {"stats": stats(ys), "x": xs, "y": ys}
  137. print(" [2D] %s: %s" % (n, stats(ys)))
  138. for n in promising3d:
  139. for sec in (1, 2):
  140. xs, ys = read3d(mc, n, sec)
  141. if ys:
  142. key = "3D:%s:sec%d" % (n, sec)
  143. waves[key] = {"stats": stats(ys), "x": xs, "y": ys}
  144. print(" [3D] %s sec%d: %s" % (n, sec, stats(ys)))
  145. results["waveforms"] = waves
  146. else:
  147. print("[如实] 力开关打开后仍无任何命中")
  148. res_path = os.path.join(OUT_DIR, "probe4_results_%s.json" % ts)
  149. with open(res_path, "w", encoding="utf-8") as f:
  150. json.dump(results, f, ensure_ascii=False, indent=2)
  151. print("RESULTS: %s" % res_path)
  152. return 0
  153. finally:
  154. if quit_after:
  155. try:
  156. mc.quit()
  157. except Exception:
  158. pass
  159. else:
  160. print("[提示] Motor-CAD 保持前台打开供检查。")
  161. if __name__ == "__main__":
  162. sys.exit(main(sys.argv[1:]))