Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit e095e8fd authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

torque converter: computation of operating point works (+ testcases green),...

torque converter: computation of operating point works (+ testcases green), similar results as with Vecto 2.2
parent e9fa6611
No related branches found
No related tags found
No related merge requests found
......@@ -8,7 +8,8 @@ using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
{
public class TorqueConverterDataReader {
public class TorqueConverterDataReader
{
public static TorqueConverterData ReadFromFile(string filename)
{
return Create(VectoCSVFile.Read(filename));
......@@ -28,36 +29,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
throw new VectoException("TorqueConverter Characteristics data must contain at least 2 lines with numeric values");
}
List<TorqueRatioCurveEntry> torqueRatio;
List<CharacteristicTorqueEntry> characteristicTorque;
List<TorqueConverterEntry> characteristicTorque;
if (HeaderIsValid(data.Columns)) {
torqueRatio = (from DataRow row in data.Rows
select
new TorqueRatioCurveEntry() {
SpeedRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.SpeedRatio),
TorqueRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.TorqueRatio)
}).ToList();
characteristicTorque = (from DataRow row in data.Rows
select
new CharacteristicTorqueEntry() {
SpeedRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.SpeedRatio),
Torque = DataTableExtensionMethods.ParseDouble(row, (string)Fields.CharacteristicTorque).SI<NewtonMeter>()
new TorqueConverterEntry() {
SpeedRatio = row.ParseDouble((string)Fields.SpeedRatio),
Torque = row.ParseDouble((string)Fields.CharacteristicTorque).SI<NewtonMeter>(),
TorqueRatio = row.ParseDouble((string)Fields.TorqueRatio)
}).ToList();
} else {
torqueRatio = (from DataRow row in data.Rows
select
new TorqueRatioCurveEntry() {
SpeedRatio = row.ParseDouble(0),
TorqueRatio = row.ParseDouble(1)
}).ToList();
characteristicTorque = (from DataRow row in data.Rows
select
new CharacteristicTorqueEntry() {
new TorqueConverterEntry() {
SpeedRatio = row.ParseDouble(0),
Torque = row.ParseDouble(2).SI<NewtonMeter>()
Torque = row.ParseDouble(2).SI<NewtonMeter>(),
TorqueRatio = row.ParseDouble(1)
}).ToList();
}
return new TorqueConverterData(torqueRatio, characteristicTorque);
return new TorqueConverterData(characteristicTorque);
}
private static bool HeaderIsValid(DataColumnCollection columns)
......
......@@ -43,14 +43,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
{
public class TorqueConverterData
{
public List<TorqueRatioCurveEntry> TorqueRatio;
public List<CharacteristicTorqueEntry> CharacteristicTorque;
public List<TorqueConverterEntry> TorqueConverterEntries;
protected internal TorqueConverterData(List<TorqueRatioCurveEntry> torqueRatio,
List<CharacteristicTorqueEntry> characteristicTorque)
protected internal TorqueConverterData(List<TorqueConverterEntry> torqueConverterEntries)
{
TorqueRatio = torqueRatio;
CharacteristicTorque = characteristicTorque;
TorqueConverterEntries = torqueConverterEntries;
}
public void GetInputTorqueAndAngularSpeed(NewtonMeter torqueOut, PerSecond angularSpeedOut, out NewtonMeter torqueIn,
......@@ -59,43 +56,55 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
var solutions = new List<double>();
var mpNorm = 1000.RPMtoRad().Value();
foreach (
var muEdge in TorqueRatio.Pairwise((item1, item2) => Edge.Create(new Point(item1.SpeedRatio, item1.TorqueRatio),
new Point(item2.SpeedRatio, item2.TorqueRatio)))) {
foreach (
var mpEdge in
CharacteristicTorque.Pairwise((item1, item2) => Edge.Create(new Point(item1.SpeedRatio, item1.Torque.Value()),
new Point(item2.SpeedRatio, item2.Torque.Value())))) {
var a = muEdge.OffsetXY * mpEdge.OffsetXY / (mpNorm * mpNorm);
var b = angularSpeedOut.Value() * (muEdge.SlopeXY * mpEdge.OffsetXY + mpEdge.SlopeXY * muEdge.OffsetXY) / mpNorm;
var c = angularSpeedOut.Value() * angularSpeedOut.Value() * mpEdge.SlopeXY * muEdge.SlopeXY / mpNorm -
torqueOut.Value();
var sol = VectoMath.QuadraticEquationSolver(a, b, c);
// Find analytic solution for torque converter operating point
// mu = f(nu) = f(n_out / n_in) = T_out / T_in
// MP1000 = f(nu) = f(n_out / n_in)
// Tq_in = MP1000(nu) * (n_in/1000)^2 = T_out / mu
//
// mu(nu) and MP1000(nu) are provided as piecewise linear functions (y = k*x+d)
// solving the equation above for n_in results in a quadratic equation
foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
var mpEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.Torque.Value()),
new Point(segment.Item2.SpeedRatio, segment.Item2.Torque.Value()));
var muEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.TorqueRatio),
new Point(segment.Item2.SpeedRatio, segment.Item2.TorqueRatio));
var edge1 = muEdge;
var edge2 = mpEdge;
var selected =
sol.Where(x => x > 0 && angularSpeedOut.Value() / x >= edge1.P1.X && angularSpeedOut.Value() / x < edge1.P2.X
&& angularSpeedOut.Value() / x >= edge2.P1.X && angularSpeedOut.Value() / x < edge2.P2.X);
solutions.AddRange(selected);
}
var a = muEdge.OffsetXY * mpEdge.OffsetXY / (mpNorm * mpNorm);
var b = angularSpeedOut.Value() * (muEdge.SlopeXY * mpEdge.OffsetXY + mpEdge.SlopeXY * muEdge.OffsetXY) /
(mpNorm * mpNorm);
var c = angularSpeedOut.Value() * angularSpeedOut.Value() * mpEdge.SlopeXY * muEdge.SlopeXY / (mpNorm * mpNorm) -
torqueOut.Value();
var sol = VectoMath.QuadraticEquationSolver(a, b, c);
var selected = sol.Where(x => x > 0
&& angularSpeedOut.Value() / x >= muEdge.P1.X && angularSpeedOut.Value() / x < muEdge.P2.X
&& angularSpeedOut.Value() / x >= mpEdge.P1.X && angularSpeedOut.Value() / x < mpEdge.P2.X);
solutions.AddRange(selected);
}
if (solutions.Count == 0) {
throw new VectoException("No solution for input torque/input speed found! n_out: {0}, tq_out: {1}", angularSpeedOut, torqueOut);
}
angularSpeedIn = solutions.Min().SI<PerSecond>();
torqueIn = 0.SI<NewtonMeter>();
var mu = MuLookup(angularSpeedOut / angularSpeedIn);
torqueIn = torqueOut / mu;
}
private double MuLookup(double nu)
{
int index;
TorqueConverterEntries.GetSection(x => x.SpeedRatio > nu, out index);
var muEdge = Edge.Create(new Point(TorqueConverterEntries[index].SpeedRatio, TorqueConverterEntries[index].TorqueRatio),
new Point(TorqueConverterEntries[index + 1].SpeedRatio, TorqueConverterEntries[index + 1].TorqueRatio));
return muEdge.SlopeXY * nu + muEdge.OffsetXY;
}
}
public class CharacteristicTorqueEntry
public class TorqueConverterEntry
{
public double SpeedRatio;
public NewtonMeter Torque;
}
public class TorqueRatioCurveEntry
{
public double SpeedRatio;
public double TorqueRatio;
}
}
\ No newline at end of file
using System;
using System.Diagnostics;
using NUnit.Framework;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox;
......@@ -9,8 +10,21 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
[TestFixture]
public class TorqueConverterDataTest
{
[Test]
public void TestTorqueConverterOperatingPoint()
[Test,
TestCase(30, 10, 1230.7, 842.8317),
TestCase(40, 10, 1081.028, 645.9384),
TestCase(50, 10, 981.7928, 528.8284),
TestCase(60, 10, 912.2327, 452.9006),
TestCase(70, 10, 860.6045, 399.6834),
TestCase(70, 30, 1433.893, 1129.279),
TestCase(90, 10, 789.4108, 330.28),
TestCase(90, 30, 1295.913, 912.1714),
TestCase(170, 30, 1055.424, 574.8998),
TestCase(170, 50, 1308.974, 900.0845),
TestCase(190, 30, 1029.455, 539.6072),
TestCase(190, 50, 1269.513, 837.2174),
TestCase(190, 70, 1465.33, 1128.088),]
public void TestTorqueConverterOperatingPoint(double nOut, double Pout, double nInExpected, double tqInExpected)
{
var tqInput = new[] {
"0,3.935741,563.6598 ",
......@@ -22,7 +36,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
"0.6,1.249399,268.4255",
"0.7,1.075149,114.9037",
};
;
var tqData =
TorqueConverterDataReader.ReadFromStream(InputDataHelper.InputDataAsStream("Speed Ratio, Torque Ratio,MP1000",
tqInput));
......@@ -30,10 +44,14 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
PerSecond inAngularSpeed;
NewtonMeter inTorque;
tqData.GetInputTorqueAndAngularSpeed(400.SI<NewtonMeter>(), 10.RPMtoRad(), out inTorque, out inAngularSpeed);
Assert.AreEqual(0, inTorque.Value());
Assert.AreEqual(0, inAngularSpeed.Value());
var outAngularSpeed = nOut.RPMtoRad();
var outTorque = (Pout * 1000).SI<Watt>() / outAngularSpeed;
tqData.GetInputTorqueAndAngularSpeed(outTorque, outAngularSpeed, out inTorque, out inAngularSpeed);
Assert.AreEqual(nInExpected.RPMtoRad().Value(), inAngularSpeed.Value(), 5);
Assert.AreEqual(tqInExpected, inTorque.Value(), 10);
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment