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

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

allow multiple solutions for torque converter operating point, select appropriate

parent 92adcb02
No related branches found
No related tags found
No related merge requests found
......@@ -62,12 +62,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
/// </summary>
/// <param name="torqueOut">torque provided at the TC output</param>
/// <param name="angularSpeedOut">angular speed at the TC output</param>
/// <param name="minSpeed"></param>
/// <returns></returns>
public TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter torqueOut, PerSecond angularSpeedOut)
public IList<TorqueConverterOperatingPoint> FindOperatingPoint(NewtonMeter torqueOut, PerSecond angularSpeedOut,
PerSecond minSpeed)
{
var solutions = new List<double>();
var mpNorm = ReferenceSpeed.Value();
var min = minSpeed == null ? 0 : minSpeed.Value();
// 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)
......@@ -88,7 +92,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
torqueOut.Value();
var sol = VectoMath.QuadraticEquationSolver(a, b, c);
var selected = sol.Where(x => x > 0
var selected = sol.Where(x => x > min
&& 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);
......@@ -98,15 +102,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
torqueOut);
}
var retVal = new TorqueConverterOperatingPoint {
OutTorque = torqueOut,
OutAngularVelocity = angularSpeedOut,
InAngularVelocity = solutions.Min().SI<PerSecond>()
};
retVal.SpeedRatio = angularSpeedOut / retVal.InAngularVelocity;
retVal.TorqueRatio = MuLookup(angularSpeedOut / retVal.InAngularVelocity);
retVal.InTorque = torqueOut / retVal.TorqueRatio;
var retVal = new List<TorqueConverterOperatingPoint>();
foreach (var sol in solutions) {
var tmp = new TorqueConverterOperatingPoint {
OutTorque = torqueOut,
OutAngularVelocity = angularSpeedOut,
InAngularVelocity = sol.SI<PerSecond>()
};
tmp.SpeedRatio = angularSpeedOut / tmp.InAngularVelocity;
tmp.TorqueRatio = MuLookup(angularSpeedOut / tmp.InAngularVelocity);
tmp.InTorque = torqueOut / tmp.TorqueRatio;
retVal.Add(tmp);
}
return retVal;
}
......@@ -139,7 +146,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio;
return retVal;
}
throw new VectoException("No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}", outAngularVelocity,
throw new VectoException(
"No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}", outAngularVelocity,
inAngularVelocity, outAngularVelocity / inAngularVelocity, TorqueConverterEntries.Last().SpeedRatio);
}
......@@ -153,7 +161,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
/// <param name="inAngularVelocity"></param>
/// <param name="outAngularSpeedEstimated"></param>
/// <returns></returns>
public TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter inTorque, PerSecond inAngularVelocity,
public TorqueConverterOperatingPoint FindOperatingPointForward(NewtonMeter inTorque, PerSecond inAngularVelocity,
PerSecond outAngularSpeedEstimated)
{
var referenceTorque = inTorque.Value() / inAngularVelocity.Value() / inAngularVelocity.Value() *
......
......@@ -29,6 +29,8 @@
* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
*/
using System.Collections.Generic;
using System.Linq;
using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils;
......@@ -254,20 +256,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
(ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, dryOperatingPoint.InAngularVelocity,
true);
var deltaTorqueConverter = (outTorque - dryOperatingPoint.OutTorque) *
(PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0;
//var deltaTorqueConverter = (outTorque - dryOperatingPoint.OutTorque) *
// (PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0;
var deltaEngine = (engineResponse.DeltaFullLoad > 0 ? engineResponse.DeltaFullLoad : 0.SI<Watt>()) +
(engineResponse.DeltaDragLoad < 0 ? -engineResponse.DeltaDragLoad : 0.SI<Watt>());
//var deltaEngine = (engineResponse.DeltaFullLoad > 0 ? engineResponse.DeltaFullLoad : 0.SI<Watt>()) +
// (engineResponse.DeltaDragLoad < 0 ? -engineResponse.DeltaDragLoad : 0.SI<Watt>());
dryOperatingPoint = outTorque.IsGreater(0) && DataBus.BrakePower.IsEqual(0)
? GetMaxPowerOperatingPoint(dt, outAngularVelocity, engineResponse)
: GetDragPowerOperatingPoint(dt, outAngularVelocity, engineResponse);
engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque,
dryOperatingPoint.InAngularVelocity, true);
//engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque,
// dryOperatingPoint.InAngularVelocity, true);
var delta = (outTorque - dryOperatingPoint.OutTorque) *
(PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0;
//var tmp = FindOperatingPoint(dryOperatingPoint.OutTorque, dryOperatingPoint.OutAngularVelocity);
//deltaTorqueConverter.Value() * (deltaEngine.IsEqual(0) ? 1 : deltaEngine.Value());
return new ResponseDryRun() {
Source = this,
......@@ -331,11 +334,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
PerSecond outAngularVelocity)
{
try {
var operatingPoint = TorqueConverter.FindOperatingPoint(outTorque, outAngularVelocity);
if (operatingPoint.InAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) {
throw new VectoException("Invalid operating point, inAngularVelocity below engine's idle speed: {0}",
operatingPoint.InAngularVelocity);
}
var operatingPointList = TorqueConverter.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed);
var operatingPoint = SelectOperatingPoint(operatingPointList);
if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) {
operatingPoint = TorqueConverter.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity);
}
......@@ -347,6 +347,24 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
}
}
private TorqueConverterOperatingPoint SelectOperatingPoint(IList<TorqueConverterOperatingPoint> operatingPointList)
{
if (operatingPointList.Count == 1) {
return operatingPointList[0];
}
var filtered = operatingPointList.Where(x =>
(x.InTorque * x.InAngularVelocity).IsSmallerOrEqual(DataBus.EngineStationaryFullPower(x.InAngularVelocity),
Constants.SimulationSettings.LineSearchTolerance.SI<Watt>()) &&
(x.InTorque * x.InAngularVelocity).IsGreaterOrEqual(DataBus.EngineDragPower(x.InAngularVelocity),
Constants.SimulationSettings.LineSearchTolerance.SI<Watt>())
).ToArray();
if (filtered.Count() == 1) {
return filtered.First();
}
return operatingPointList[0];
}
private TorqueConverterOperatingPoint GetDragPowerOperatingPoint(Second dt, PerSecond outAngularVelocity,
ResponseDryRun engineResponse)
{
......@@ -430,12 +448,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
container[ModalResultField.TC_angularSpeedOut] = CurrentState.TorqueConverterOperatingPoint.OutAngularVelocity;
var avgOutVelocity = ((PreviousState.TorqueConverterOperatingPoint != null
? PreviousState.TorqueConverterOperatingPoint.OutAngularVelocity
: PreviousState.InAngularVelocity) +
? PreviousState.TorqueConverterOperatingPoint.OutAngularVelocity
: PreviousState.InAngularVelocity) +
CurrentState.TorqueConverterOperatingPoint.OutAngularVelocity) / 2.0;
var avgInVelocity = ((PreviousState.TorqueConverterOperatingPoint != null
? PreviousState.TorqueConverterOperatingPoint.InAngularVelocity
: PreviousState.InAngularVelocity) +
? PreviousState.TorqueConverterOperatingPoint.InAngularVelocity
: PreviousState.InAngularVelocity) +
CurrentState.TorqueConverterOperatingPoint.InAngularVelocity) / 2.0;
container[ModalResultField.P_TC_out] = CurrentState.OutTorque * avgOutVelocity;
container[ModalResultField.P_TC_loss] = CurrentState.InTorque * avgInVelocity -
......
using TUGraz.VectoCommon.Exceptions;
using System.Collections.Generic;
using System.Linq;
using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Configuration;
......@@ -41,14 +43,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
{
var operatingPoint = ModelData.FindOperatingPoint(outTorque, outAngularVelocity);
var operatingPointList = ModelData.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed);
var operatingPoint = SelectOperatingPoint(operatingPointList);
var retVal = NextComponent.Initialize(operatingPoint.InTorque, operatingPoint.InAngularVelocity);
PreviousState.SetState(operatingPoint.InTorque, operatingPoint.InAngularVelocity, operatingPoint.OutTorque,
operatingPoint.OutAngularVelocity);
return retVal;
}
public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
bool dryRun = false)
{
......@@ -153,7 +156,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
PerSecond outAngularVelocity)
{
try {
var operatingPoint = ModelData.FindOperatingPoint(outTorque, outAngularVelocity);
var operatingPointList = ModelData.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed);
var operatingPoint = SelectOperatingPoint(operatingPointList);
if (operatingPoint.InAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) {
throw new VectoException("Invalid operating point, inAngularVelocity below engine's idle speed: {0}",
operatingPoint.InAngularVelocity);
......@@ -169,6 +173,24 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
}
}
private TorqueConverterOperatingPoint SelectOperatingPoint(IList<TorqueConverterOperatingPoint> operatingPointList)
{
if (operatingPointList.Count == 1) {
return operatingPointList[0];
}
var filtered = operatingPointList.Where(x =>
(x.InTorque * x.InAngularVelocity).IsSmallerOrEqual(DataBus.EngineStationaryFullPower(x.InAngularVelocity),
Constants.SimulationSettings.LineSearchTolerance.SI<Watt>()) &&
(x.InTorque * x.InAngularVelocity).IsGreaterOrEqual(DataBus.EngineDragPower(x.InAngularVelocity),
Constants.SimulationSettings.LineSearchTolerance.SI<Watt>())
).ToArray();
if (filtered.Count() == 1) {
return filtered.First();
}
return operatingPointList[0];
}
protected override void DoWriteModalResults(IModalDataContainer container)
{
if (CurrentState.OperatingPoint == null) {
......
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NLog.Targets;
using NUnit.Framework;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Configuration;
......@@ -52,7 +54,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
var outAngularSpeed = nOut.RPMtoRad();
var outTorque = (Pout * 1000).SI<Watt>() / outAngularSpeed;
var result = tqData.FindOperatingPoint(outTorque, outAngularSpeed);
var resultList = tqData.FindOperatingPoint(outTorque, outAngularSpeed, 0.SI<PerSecond>());
Assert.AreEqual(1, resultList.Count);
var result = resultList[0];
Assert.AreEqual(outAngularSpeed.Value(), result.OutAngularVelocity.Value(), 1e-3);
Assert.AreEqual(outTorque.Value(), result.OutTorque.Value(), 1e-3);
......@@ -85,13 +89,16 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
tqInput), 1000.RPMtoRad(), tqLimit.RPMtoRad());
var operatingPoint = tqData.FindOperatingPoint(tqIn.SI<NewtonMeter>(), nIn.RPMtoRad(), null);
var operatingPoint = tqData.FindOperatingPointForward(tqIn.SI<NewtonMeter>(), nIn.RPMtoRad(), null);
Assert.AreEqual(operatingPoint.InTorque.Value(), tqIn, 1e-6);
Assert.AreEqual(operatingPoint.InAngularVelocity.Value(), nIn.RPMtoRad().Value(), 1e-6);
var reverseOP = tqData.FindOperatingPoint(operatingPoint.OutTorque, operatingPoint.OutAngularVelocity);
var resultList = tqData.FindOperatingPoint(operatingPoint.OutTorque, operatingPoint.OutAngularVelocity,
0.SI<PerSecond>());
Assert.AreEqual(1, resultList.Count);
var reverseOP = resultList[0];
Assert.AreEqual(operatingPoint.InTorque.Value(), reverseOP.InTorque.Value(), 1e-6);
Assert.AreEqual(operatingPoint.OutTorque.Value(), reverseOP.OutTorque.Value(), 1e-6);
......@@ -131,7 +138,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
foreach (var entry in testData) {
var torqueTCOut = entry.Item1.SI<NewtonMeter>();
var angularSpeedOut = entry.Item2.RPMtoRad();
var result = tqData.FindOperatingPoint(torqueTCOut, angularSpeedOut);
var result = tqData.FindOperatingPoint(torqueTCOut, angularSpeedOut, 0.SI<PerSecond>()).First();
Debug.WriteLine("n_out: {0}, tq_out: {1}, n_in: {2}, Tq_in: {3}", angularSpeedOut.Value() / Constants.RPMToRad,
torqueTCOut.Value(), result.InAngularVelocity.Value() / Constants.RPMToRad, result.InTorque.Value());
}
......@@ -176,9 +183,80 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
var outAngularSpeed = nOut.RPMtoRad();
var outTorque = (Pout * 1000).SI<Watt>() / outAngularSpeed;
var result = tqData.FindOperatingPoint(outTorque, outAngularSpeed);
var resultList = tqData.FindOperatingPoint(outTorque, outAngularSpeed, 0.SI<PerSecond>());
Assert.AreEqual(1, resultList.Count);
var result = resultList[0];
Assert.IsTrue(result.InAngularVelocity.Value() > tqLimit.Value());
}
[TestCase()]
public void TestForwardBackward()
{
var tqLimit = 1600.RPMtoRad();
var tqInput = new[] {
"0,4.6,708 ",
"0.1,3.7,641 ",
"0.2,2.9,560 ",
"0.3,2.4,465 ",
"0.4,1.8,356 ",
"0.5,1.4,251 ",
"0.6,0.9,166 ",
"0.735,0.9,1 ",
"0.738,1.361,0 ",
"0.808,1.351,-40 ",
"0.898,1.349,-80 ",
"1.01,1.338,-136 ",
"1.154,1.327,-217 ",
"1.347,1.316,-335 ",
"1.616,1.305,-529 ",
"3 ,1.294,-729 ",
};
var tqInput_1 = new[] {
"0.0,1.80,377.80 ",
"0.1,1.71,365.21 ",
"0.2,1.61,352.62 ",
"0.3,1.52,340.02 ",
"0.4,1.42,327.43 ",
"0.5,1.33,314.84 ",
"0.6,1.23,302.24 ",
"0.7,1.14,264.46 ",
"0.8,1.04,226.68 ",
"0.9,0.95,188.90 ",
"1.0,0.95,0.00 ",
"1.100,0.99,-40.34 ",
"1.222,0.98,-80.34 ",
"1.375,0.97,-136.11 ",
"1.571,0.96,-216.52 ",
"1.833,0.95,-335.19 ",
"2.200,0.94,-528.77 ",
"2.750,0.93,-883.40 ",
"4.400,0.92,-2462.17 ",
"11.000,0.91,-16540.98 ",
};
var tqData =
TorqueConverterDataReader.ReadFromStream(InputDataHelper.InputDataAsStream("Speed Ratio, Torque Ratio,MP1000",
tqInput), 1000.RPMtoRad(), tqLimit);
var operatingPoint = tqData.FindOperatingPointForPowerDemand(20000.SI<Watt>(), 113.5.SI<PerSecond>(),
1200.RPMtoRad(), 4.SI<KilogramSquareMeter>(), 0.5.SI<Second>());
var tmp = tqData.FindOperatingPoint(operatingPoint.OutTorque, operatingPoint.OutAngularVelocity, 0.RPMtoRad());
var backward = tmp.First();
Debug.WriteLine(operatingPoint);
Debug.WriteLine(operatingPoint.InAngularVelocity * operatingPoint.InTorque);
Debug.WriteLine(backward);
Debug.WriteLine(backward.InAngularVelocity * backward.InTorque);
Assert.AreEqual(backward.OutAngularVelocity.Value(), operatingPoint.OutAngularVelocity.Value(), 1e-9);
Assert.AreEqual(backward.OutTorque.Value(), operatingPoint.OutTorque.Value(), 1e-9);
Assert.AreEqual(backward.InAngularVelocity.Value(), operatingPoint.InAngularVelocity.Value(), 1e-9);
Assert.AreEqual(backward.InTorque.Value(), operatingPoint.InTorque.Value(), 1e-9);
}
}
}
\ 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