private VoltageLimitCurve buildVoltageLimitCurve(int count = 50, double Imax = 55, double Umax = 140, double max_speed = 6000) { var mtpa = buildTableMaxtorquePerAmple(); VoltageLimitCurve vlc = new VoltageLimitCurve() { Imax = Imax, Umax = Umax, MaxSpeed = max_speed, }; for (int i = 0; i < count + 1; i++) { double t = mtpa.GetMaxTorqueWithCurrentMagnitude(i * Imax / count); var idq = mtpa.GetCurrentForTorque(t); // look for speed, that is suitable for given current (in max torque condition) and u=Umax double ss = 0; bool success = Brent.TryFindRoot(s => { var data_ = calculatePointdata(idq.d, idq.q, s); var u_ = Math.Sqrt(data_.ud * data_.ud + data_.uq * data_.uq); return(u_ - Umax); }, 100, max_speed, 1e-3, 100, out ss); if (success) { vlc.speeds.Add(ss); vlc.torques.Add(t); vlc.currents.Add(idq); } } return(vlc); }
private void bt_show_maxtorque_capa_curve_Click(object sender, EventArgs e) { try { double Imax = double.Parse(tb_Imax.Text); double Umax = double.Parse(tb_Umax.Text); double max_speed = double.Parse(tb_maxSpeed.Text); MaxtorqueCapabilityCurve mtcc = buildMaxtorqueCapabilityCurve(50, Imax, Umax, max_speed); VoltageLimitCurve vlc = buildVoltageLimitCurve(50, Imax, Umax, max_speed); GraphWindow tc = new GraphWindow(); tc.addData("Torque-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.maxtorques.ToArray())); tc.addData("Current-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.Magnitude).ToArray())); tc.addData("CurrentPhase-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.Phase).ToArray())); tc.addData("Voltage-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.voltages.Select(f => f.Magnitude).ToArray())); tc.addData("Power-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.power.ToArray())); tc.addData("Efficiency", new PointPairList(mtcc.speeds.ToArray(), mtcc.effs.ToArray())); tc.addData("Boundary-Torque-speed1", new PointPairList(vlc.speeds.ToArray(), vlc.torques.ToArray())); tc.addData("(iq,id)", new PointPairList(mtcc.currents.Select(f => f.d).ToArray(), mtcc.currents.Select(f => f.q).ToArray())); tc.addData("id-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.d).ToArray())); tc.addData("iq-speed", new PointPairList(mtcc.speeds.ToArray(), mtcc.currents.Select(f => f.q).ToArray())); tc.Show(); } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message); } }
private void bt_showmap_Click(object sender, EventArgs e) { bool success = true; double Imax = 0; success = success && double.TryParse(tb_Imax.Text, out Imax); double Umax = 0; success = success && double.TryParse(tb_Umax.Text, out Umax); double max_speed = 0; success = success && double.TryParse(tb_maxSpeed.Text, out max_speed); string config = string.Format("{0},{1},{2}", Imax, Umax, max_speed); MapType maptype = MapType.power; Enum.TryParse <MapType>(comboBox_maptype.Text, true, out maptype); if (!success) { MessageBox.Show("Error parse text to double"); return; } var mtpa = buildTableMaxtorquePerAmple(); int n = 100; double x0 = 0; double x1 = max_speed; double y0 = 0; double y1 = mtpa.GetMaxTorqueWithCurrentMagnitude(Imax); if (last_config != config) { effMap = buildEfficiencyMap(50, 100, Imax, Umax, max_speed); last_config = config; } var data = effMap.power; string title = "Power (W)"; switch (maptype) { case MapType.power: data = effMap.power; title = "Power (W)"; break; case MapType.efficiency: data = effMap.efficiency; title = "Efficiency (%)"; break; case MapType.windingloss: data = effMap.windingloss; title = "Winding loss (W)"; break; case MapType.rotor_coreloss: data = effMap.rotor_coreloss; title = "Rotor core loss (W)"; break; case MapType.stator_coreloss: data = effMap.stator_coreloss; title = "Stator loss (W)"; break; case MapType.coreloss: data = effMap.coreloss; title = "Core loss (W)"; break; case MapType.total_loss: data = effMap.totalloss; title = "Total loss (W)"; break; case MapType.voltage: data = effMap.voltage; title = "Voltage (V)"; break; case MapType.current: data = effMap.current; title = "Current (A)"; break; case MapType.beta: data = effMap.beta; title = "Beta (degree)"; break; case MapType.Ld: data = effMap.Ld; title = "Ld (mH)"; break; case MapType.Lq: data = effMap.Lq; title = "Ld (mH)"; break; default: break; } double fmin = double.MaxValue; for (int i = 0; i < data.GetLength(0); i++) { for (int j = 0; j < data.GetLength(1); j++) { if (data[i, j] >= 0 && fmin > data[i, j]) { fmin = data[i, j]; } } } var model = new PlotModel { Title = title, }; model.Axes.Add(new LinearColorAxis { Position = AxisPosition.Right, Palette = OxyPalettes.Jet(500), HighColor = OxyColors.Gray, LowColor = OxyColors.White, Minimum = fmin, //Maximum = 100, Title = title }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Speed", //MajorGridlineStyle = LineStyle.Solid, //MinorGridlineStyle = LineStyle.Solid, //MajorGridlineColor = OxyColor.FromAColor(40, c), //MinorGridlineColor = OxyColor.FromAColor(20, c) }); model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Torque", //AbsoluteMinimum = 0, //Minimum = 0, //MajorGridlineStyle = LineStyle.Solid, //MinorGridlineStyle = LineStyle.Solid, //MajorGridlineColor = OxyColor.FromAColor(40, c), //MinorGridlineColor = OxyColor.FromAColor(20, c) }); var hms = new HeatMapSeries { X0 = x0, X1 = x1, Y0 = y0, Y1 = y1, Data = data, Interpolate = true, }; model.Series.Add(hms); // contour var cs = new ContourSeries { //Color = OxyColors.Gray, //FontSize = 12, //ContourLevelStep = double.NaN, //LabelBackground = OxyColors.White, ColumnCoordinates = effMap.speed_points, RowCoordinates = effMap.torque_points, Data = data, }; if (cs.Data == effMap.efficiency) { cs.ContourLevels = new double[] { 0, 20, 40, 60, 80, 90, 91, 92, 93, 94, 95, 95.2, 95.4, 95.6, 95.8, 96, 96.2, 97, 98, 99 }; model.Series.Add(cs); } // max-torque capability curve MaxtorqueCapabilityCurve mtcc = buildMaxtorqueCapabilityCurve(100, Imax, Umax, max_speed); var mtcc_series = new LineSeries() { LineStyle = LineStyle.Solid, Color = OxyColor.FromArgb(255, 0, 0, 0), StrokeThickness = 3, }; for (int i = 0; i < mtcc.speeds.Count; i++) { mtcc_series.Points.Add(new OxyPlot.DataPoint(mtcc.speeds[i], mtcc.maxtorques[i])); } model.Series.Add(mtcc_series); // voltage limit curve 1 VoltageLimitCurve vlc = buildVoltageLimitCurve(100, Imax, Umax, max_speed); var vlc_series = new LineSeries() { LineStyle = LineStyle.Dash, StrokeThickness = 1, }; for (int i = 0; i < vlc.speeds.Count; i++) { vlc_series.Points.Add(new OxyPlot.DataPoint(vlc.speeds[i], vlc.torques[i])); } model.Series.Add(vlc_series); plot.Model = model; }
private EfficiencyMap buildEfficiencyMap(int torque_count, int speed_count, double Imax, double Umax, double max_speed) { MaxtorqueCapabilityCurve mtcc = buildMaxtorqueCapabilityCurve(speed_count, Imax, Umax, max_speed); VoltageLimitCurve vlc = buildVoltageLimitCurve(speed_count, Imax, Umax, max_speed); var em = new EfficiencyMap() { // input Imax = Imax, Umax = Umax, MaxSpeed = max_speed, // axis speed_points = new double[speed_count + 1], torque_points = new double[torque_count + 1], // value power = new double[speed_count + 1, torque_count + 1], windingloss = new double[speed_count + 1, torque_count + 1], rotor_coreloss = new double[speed_count + 1, torque_count + 1], stator_coreloss = new double[speed_count + 1, torque_count + 1], coreloss = new double[speed_count + 1, torque_count + 1], totalloss = new double[speed_count + 1, torque_count + 1], efficiency = new double[speed_count + 1, torque_count + 1], voltage = new double[speed_count + 1, torque_count + 1], current = new double[speed_count + 1, torque_count + 1], beta = new double[speed_count + 1, torque_count + 1], Ld = new double[speed_count + 1, torque_count + 1], Lq = new double[speed_count + 1, torque_count + 1], }; em.power.Fill2D(double.NaN); em.windingloss.Fill2D(double.NaN); em.rotor_coreloss.Fill2D(double.NaN); em.stator_coreloss.Fill2D(double.NaN); em.coreloss.Fill2D(double.NaN); em.totalloss.Fill2D(double.NaN); em.efficiency.Fill2D(double.NaN); em.voltage.Fill2D(double.NaN); em.current.Fill2D(double.NaN); em.beta.Fill2D(double.NaN); em.Ld.Fill2D(double.NaN); em.Lq.Fill2D(double.NaN); var mtpa = buildTableMaxtorquePerAmple(); double max_t = mtpa.GetMaxTorqueWithCurrentMagnitude(Imax); LinearSpline torqueCapabilityLimit = LinearSpline.Interpolate(mtcc.speeds, mtcc.maxtorques); for (int i = 0; i < speed_count + 1; i++) { for (int j = 0; j < torque_count + 1; j++) { // speed double speed = max_speed * i / speed_count; em.speed_points[i] = speed; // torque double t = max_t * j / torque_count; em.torque_points[j] = t; double max_possible_torque = torqueCapabilityLimit.Interpolate(speed); if (t > max_possible_torque) { continue; } // speed limit 1 double speed1 = vlc.GetMaxSpeedForTorque(t); APointData data = null; if (t == 0) { data = calculatePointdata(0, 0, speed); } // zone 1 else if (speed <= speed1) { Fdq idq = mtpa.GetCurrentForTorque(t); if (double.IsNaN(idq.d) || double.IsNaN(idq.q)) { data = null; } else { data = calculatePointdata(idq.d, idq.q, speed); } } else { Fdq idq = getCurrentForZone2(t, speed, Imax, Umax); if (double.IsNaN(idq.d) || double.IsNaN(idq.q)) { data = null; } else { data = calculatePointdata(idq.d, idq.q, speed); } } if (data != null) { em.rotor_coreloss[i, j] = data.rotorloss; em.stator_coreloss[i, j] = data.statorloss; em.coreloss[i, j] = data.rotorloss + data.statorloss; em.windingloss[i, j] = data.copperloss; em.totalloss[i, j] = data.copperloss + data.rotorloss + data.statorloss; em.power[i, j] = data.power; em.efficiency[i, j] = 100 * data.power / (data.power + em.totalloss[i, j]); em.voltage[i, j] = data.voltage; em.current[i, j] = data.current; em.beta[i, j] = data.beta; em.Ld[i, j] = double.IsNaN(data.Ld) || data.Ld < 0 ? -0.0001 : data.Ld * 1000; //to mH em.Lq[i, j] = double.IsNaN(data.Ld) || data.Ld < 0 ? -0.0001 : data.Lq * 1000; //to mH } } } return(em); }