private Fdq getCurrentForZone2(double torque, double speed, double Imax, double Umax) { VoltageLimitEllipse vle = null; string key = string.Format("{0},{1},{2}", Imax, Umax, speed); if (dict_vle.ContainsKey(key)) { vle = dict_vle[key]; } else { vle = buildVoltageLimitEllipse(speed, 100, Imax, Umax); dict_vle[key] = vle; } var range = Enumerable.Range(0, vle.maxtorque_point); // find point on Voltage limit ellipse that bring given torque LinearSpline spline = LinearSpline.Interpolate(range.Select(i => vle.torques[i]), range.Select(i => vle.curve[i].d)); double id = spline.Interpolate(torque); // get iq from this id var maxiq_point = vle.curve[vle.maxtorque_point]; var minid_point = vle.curve[vle.minid_point]; if (id < maxiq_point.d || minid_point.d < id) { return(default(Fdq)); } LinearSpline spline2 = LinearSpline.Interpolate(vle.curve.Select(f => f.d), vle.curve.Select(f => f.q)); double iq = spline2.Interpolate(id); return(new Fdq { d = id, q = iq, }); }
private VoltageLimitEllipse buildVoltageLimitEllipse(double speed, int count = 50, double Imax = 55, double Umax = 140) { var vle = new VoltageLimitEllipse { speed = speed, Imax = Imax, Umax = Umax, curve = new List <Fdq>(), torques = new List <double>(), }; double maxt = 0; bool minfound = false; int index = 0; for (int j = 0; j < count + 1; j++) { double id = -Imax * j / count; double iq; double t = 0; bool bb = Brent.TryFindRoot(iq_ => { var d = calculatePointdata(id, iq_, speed); double u = Math.Sqrt(d.ud * d.ud + d.uq * d.uq); t = d.torque; return(u - Umax); }, 0, Imax, 1e-5, 100, out iq); if (bb) { var idq = new Fdq { d = id, q = iq }; if (maxt < t) { maxt = t; vle.maxtorque_point = index; } if (!minfound) { vle.minid_point = index; minfound = true; } vle.curve.Add(idq); vle.torques.Add(t); index++; } } if (vle.curve[0].d < 0) { Fdq idq1 = vle.curve[0]; Fdq idq2 = vle.curve[1]; Fdq idq0 = new Fdq { d = idq1.d + (Imax / count) * (idq1.q / idq2.q) / (1 - idq1.q / idq2.q), q = 0, }; vle.curve.Insert(0, idq0); vle.torques.Insert(0, 0); vle.maxtorque_point++; } return(vle); }