# 2horse_femm42.py - 2-horse motor frequency sweep (port of 2horse_femm42.lua)
# Sweeps frequency, solves at each, extracts flux linkage and torque,
# writes results to a file.

# open up the base geometry file
open("2horse.fem")
import json
import math
_csv = open("outputs/sweep.csv", "w")
_csv.write("frequency_Hz,current_re_A,current_im_A,voltage_re_V,voltage_im_V,flux_re_Wbturn,flux_im_Wbturn,full_flux_re_Wbturn,full_flux_im_Wbturn,quadrant_torque_Nm,full_torque_Nm,nodes,elements\n")
_rows = []
def _p(x):
    if isinstance(x,complex): return (x.real,x.imag)
    return (float(x),0.0)

# save in a temporary file for purposes of
# performing the analysis
mi_saveas("temp.fem")

for k in range(1, 13):

    freq = k / 4

    # change the frequency to the desired one
    # for this particular iteration
    mi_probdef(freq, "millimeters", "planar", 1e-8, 100, 20)

    # run the analysis and load the solution
    mi_analyze(1)
    mi_loadsolution()

    # look at the flux linkage for phase A.
    i, v, flux = mo_getcircuitproperties("A")

    # get the torque on the rotor
    mo_groupselectblock(4)
    torque = mo_blockintegral(22)

    # write results to a data file, multiplying by 4 to get
    # the results for all 4 poles of the machine.
    handle = open("outputs/results_complex_safe.txt", "a")
    _i,_v,_f,_t = _p(i),_p(v),_p(flux),_p(torque)
    _row = [freq,_i[0],_i[1],_v[0],_v[1],_f[0],_f[1],4*_f[0],4*_f[1],_t[0],4*_t[0],int(mo_numnodes()),int(mo_numelements())]
    _csv.write(",".join("%.17g" % x for x in _row)+"\n")
    _csv.flush()
    _rows.append(_row)
    handle.write("%.14g\t%s\t%s\n" % (freq,str(4*flux),str(4*torque)))
    print("NATIVE_SWEEP_POINT "+json.dumps(_row))
    handle.close()

_csv.close()
assert len(_rows)==12
assert all(abs(row[0]-(idx+1)/4.0)<1e-12 for idx,row in enumerate(_rows))
assert all(math.isfinite(v) for row in _rows for v in row)
f=open("outputs/sweep-validation.json","w");f.write(json.dumps({"points":len(_rows),"expected_points":12,"frequency_min_Hz":_rows[0][0],"frequency_max_Hz":_rows[-1][0],"finite":True,"full_machine_multiplier":4,"upstream_solver_loop_preserved":True}));f.close()
