# -*- coding: utf-8 -*-
"""
对标 V3.0 解析报告的 FEA 验证扫描
==================================
参照《轴向磁通电机轴向磁拉力计算与轴承选型校核报告V3.0-20260826.pdf》:
  - 其基准: 磁钢 20°C, 空载 Fz=483 N (中值口径 500 N)
  - 其表3-3: g=0.6/1.0/1.5 mm -> 601/483/378 N, kneg(1mm)=250 N/mm
本模型 .mot 磁钢温度默认 100°C (Br -0.12%/K), 首先归一到 20°C 再扫气隙。

工况: 磁钢 20°C x 气隙 {0.6, 1.0, 1.5} mm, 各求解一次, 读 OC/OL 净轴向力
及气隙磁密; 有限差分求磁负刚度 kneg。

用法: python axial_compare.py [--quit]
"""
import json
import os
import sys
import time

BASE = os.path.dirname(os.path.abspath(__file__))
MOT_SRC = os.path.join(BASE, "MARS-12S10P_SSSR_D76-C150_V5.0-0819.mot")
OUT_DIR = os.path.join(BASE, "output_motorcad")

GAPS = [0.6, 1.0, 1.5]
MAGNET_TEMP_C = 20.0
MAX_TSTEPS = 64
MAX_NODES = 40


def stats(ys):
    if not ys:
        return None
    return {"mean": sum(ys) / len(ys), "min": min(ys), "max": max(ys),
            "pk2pk": max(ys) - min(ys), "n": len(ys)}


def read_nodes(mc, graph, sec, tstep):
    xs, ys = [], []
    for i in range(MAX_NODES):
        try:
            x, y = mc.get_magnetic_3d_graph_point(graph, sec, i, tstep)
        except Exception:
            break
        xs.append(x)
        ys.append(y)
    return xs, ys


def net_force_series(mc, graph):
    series = []
    for tstep in range(MAX_TSTEPS):
        total, got = 0.0, False
        for sec in (1, 2):
            xs, ys = read_nodes(mc, graph, sec, tstep)
            if not ys:
                continue
            got = True
            nu = len(ys) - 1 if (len(xs) > 1 and
                                 abs(xs[-1] - xs[0] - 360.0) < 1e-6) else len(ys)
            total += sum(ys[:nu])
        if not got:
            break
        series.append(total)
    return series


def read_2d(mc, graph, maxpts=64):
    ys = []
    for i in range(maxpts):
        try:
            _, y = mc.get_magnetic_graph_point(graph, i)
        except Exception:
            break
        ys.append(y)
    return ys


def main(argv):
    quit_after = "--quit" in argv
    os.makedirs(OUT_DIR, exist_ok=True)
    ts = time.strftime("%m%d_%H%M%S")

    from ansys.motorcad.core import MotorCAD
    print("启动 Motor-CAD (前台) ...")
    mc = MotorCAD()
    try:
        mc.set_visible(True)   # /SCRIPTING 模式部分机器窗口不显示, 强制可见
    except Exception:
        pass
    results = {"when": ts, "magnet_temp_C": MAGNET_TEMP_C,
               "reference": "V3.0 报告表3-1/3-3: 20°C, g=0.6/1.0/1.5 -> "
                            "601/483/378 N, kneg(1mm)=250 N/mm",
               "cases": []}
    try:
        mc.load_from_file(MOT_SRC)
        out_mot = os.path.join(OUT_DIR, "MARS_SSSR_compare_%s.mot" % ts)
        mc.save_to_file(out_mot)
        results["work_mot"] = out_mot

        t_before = mc.get_variable("Magnet_Temperature")
        results["magnet_temp_before_C"] = t_before
        mc.set_variable("Magnet_Temperature", MAGNET_TEMP_C)
        print("磁钢温度: %s -> %s °C" % (t_before, MAGNET_TEMP_C))
        for var in ["ElectromagneticForcesCalc_Load",
                    "ElectromagneticForcesCalc_OC"]:
            mc.set_variable(var, True)

        for g in GAPS:
            mc.set_variable("Airgap", g)
            back = mc.get_variable("Airgap")
            print("== 气隙 %.1f mm (回读 %s), 求解 ..." % (g, back))
            t0 = time.time()
            mc.do_magnetic_calculation()
            dt = time.time() - t0
            case = {"airgap_mm": back, "solve_seconds": dt}
            for graph, key in [("Fr_Rotor_OC_Lumped", "F_OC"),
                               ("Fr_Rotor_OL_Lumped", "F_OL")]:
                s = net_force_series(mc, graph)
                case[key] = stats(s)
            bys = read_2d(mc, "FluxDensityAirgap")
            if bys:
                case["B2_mean_T2"] = sum(b * b for b in bys) / len(bys)
            print("   F_OC=%.1f N, F_OL=%.1f N, mean(B²)=%.3f (耗时 %.0fs)"
                  % (case["F_OC"]["mean"], case["F_OL"]["mean"],
                     case.get("B2_mean_T2", -1), dt))
            results["cases"].append(case)

        # ---- 磁负刚度 (有限差分, OC 口径) ----
        cs = results["cases"]
        if len(cs) == 3:
            f = [c["F_OC"]["mean"] for c in cs]
            g0, g1, g2 = [c["airgap_mm"] for c in cs]
            k_low = -(f[1] - f[0]) / (g1 - g0)     # 0.6~1.0 段
            k_high = -(f[2] - f[1]) / (g2 - g1)    # 1.0~1.5 段
            k_mid = -(f[2] - f[0]) / (g2 - g0)     # 全段中心差分
            results["kneg_N_per_mm"] = {"seg_0.6_1.0": k_low,
                                        "seg_1.0_1.5": k_high,
                                        "central_at_1.0": k_mid}
            print("kneg: 0.6~1.0段 %.0f, 1.0~1.5段 %.0f, 中心差分 %.0f N/mm "
                  "(报告解析值 250)" % (k_low, k_high, k_mid))

        res_path = os.path.join(OUT_DIR, "compare_results_%s.json" % ts)
        with open(res_path, "w", encoding="utf-8") as fjson:
            json.dump(results, fjson, ensure_ascii=False, indent=2)
        print("RESULTS: %s" % res_path)
        return 0
    finally:
        if quit_after:
            try:
                mc.quit()
            except Exception:
                pass
        else:
            print("[提示] Motor-CAD 保持前台打开供检查。")


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
