diff --git a/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs b/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs index 36815a8a1622d3fd2cad74d46d056c16fa64846b..ade896a87e7d236cfccc858faed219b287106723 100644 --- a/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs +++ b/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs @@ -63,8 +63,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data return new RetarderLossMap { _entries = entries }; } - public NewtonMeter RetarderLoss(PerSecond angularVelocity) + public NewtonMeter RetarderLoss(PerSecond angularVelocity, bool allowExtrapolation) { + if (angularVelocity < _entries.First().RetarderSpeed) { + if (!allowExtrapolation) { + throw new VectoSimulationException("angular velocity {0} below min. entry in retarder loss map ({1})", + angularVelocity, _entries.First().RetarderSpeed); + } + Log.Warn("Extrapolating retarder losses! Angular velocity {0} below min. entry in retarder loss map ({1})", + angularVelocity, _entries.First().RetarderSpeed); + } + if (angularVelocity > _entries.Last().RetarderSpeed) { + if (!allowExtrapolation) { + throw new VectoSimulationException("angular velocity {0} above max. entry in retarder loss map ({1})", + angularVelocity, _entries.Last().RetarderSpeed); + } + Log.Warn("Extrapolating retarder losses! Angular velocity {0} above max. entry in retarder loss map ({1})", + angularVelocity, _entries.Last().RetarderSpeed); + } + var idx = FindIndex(angularVelocity); return VectoMath.Interpolate(_entries[idx - 1].RetarderSpeed, _entries[idx].RetarderSpeed, _entries[idx - 1].TorqueLoss, _entries[idx].TorqueLoss, angularVelocity); diff --git a/VectoCoreTest/Models/SimulationComponent/RetarderTest.cs b/VectoCoreTest/Models/SimulationComponent/RetarderTest.cs index fa3ca751c8323ec639b4baae4f9661d8a3fee4b3..75b2f73eb97b8f094d4d7d1e79ff1a7192256c3d 100644 --- a/VectoCoreTest/Models/SimulationComponent/RetarderTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/RetarderTest.cs @@ -17,10 +17,13 @@ */ using System; +using System.Runtime.InteropServices; using Microsoft.VisualStudio.TestTools.UnitTesting; +using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Tests.Integration; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; @@ -68,5 +71,95 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Assert.AreEqual(1550.RPMtoRad().Value(), nextRequest.AngularVelocity.Value(), Delta); Assert.AreEqual(50 + 14.81, nextRequest.Torque.Value(), Delta); } + + [TestMethod] + public void RetarderRatioTest() + { + var vehicle = new VehicleContainer(null, null, ExecutionMode.Engineering); + var retarderData = RetarderLossMap.ReadFromFile(RetarderLossMapFile); + var retarder = new Retarder(vehicle, retarderData, 2.0); + + var nextRequest = new MockTnOutPort(); + + retarder.InPort().Connect(nextRequest); + var outPort = retarder.OutPort(); + + var absTime = 0.SI<Second>(); + var dt = 0.SI<Second>(); + + // -------- + outPort.Initialize(0.SI<NewtonMeter>(), 10.RPMtoRad()); + outPort.Request(absTime, dt, 0.SI<NewtonMeter>(), 10.RPMtoRad()); + + Assert.AreEqual(10.RPMtoRad().Value(), nextRequest.AngularVelocity.Value(), Delta); + Assert.AreEqual(5.002, nextRequest.Torque.Value(), Delta); + + // -------- + outPort.Initialize(100.SI<NewtonMeter>(), 1000.RPMtoRad()); + outPort.Request(absTime, dt, 100.SI<NewtonMeter>(), 1000.RPMtoRad()); + + Assert.AreEqual(1000.RPMtoRad().Value(), nextRequest.AngularVelocity.Value(), Delta); + Assert.AreEqual(109, nextRequest.Torque.Value(), Delta); + + // -------- + outPort.Initialize(50.SI<NewtonMeter>(), 1550.RPMtoRad()); + outPort.Request(absTime, dt, 50.SI<NewtonMeter>(), 1550.RPMtoRad()); + + Assert.AreEqual(1550.RPMtoRad().Value(), nextRequest.AngularVelocity.Value(), Delta); + Assert.AreEqual(50 + 13.89, nextRequest.Torque.Value(), Delta); // extrapolated + } + + [TestMethod] + public void RetarderDeclarationTest() + { + var retarderData = RetarderLossMap.ReadFromFile(RetarderLossMapFile); + var declVehicle = new VehicleContainer(null, null, ExecutionMode.Declaration); + var retarder = new Retarder(declVehicle, retarderData, 2.0); + var nextRequest = new MockTnOutPort(); + + retarder.InPort().Connect(nextRequest); + var outPort = retarder.OutPort(); + + var absTime = 0.SI<Second>(); + var dt = 0.SI<Second>(); + + // -------- + AssertHelper.Exception<VectoSimulationException>(() => outPort.Initialize(50.SI<NewtonMeter>(), 1550.RPMtoRad()), + "angular velocity 324.6312 [1/s] above max. entry in retarder loss map (240.8554 [1/s])"); + } + + [TestMethod] + public void RetarderDataSorting() + { + var retarderEntries = new[] { + "100,10.02", + "0,10", + "200,10.08", + "500,10.5", + "300,10.18", + "400,10.32", + }; + var retarderTbl = + VectoCSVFile.ReadStream(InputDataHelper.InputDataAsStream("Retarder Speed [rpm],Loss Torque [Nm]", + retarderEntries)); + var vehicle = new VehicleContainer(null, null, ExecutionMode.Engineering); + var retarderData = RetarderLossMap.Create(retarderTbl); + var retarder = new Retarder(vehicle, retarderData, 2.0); + + var nextRequest = new MockTnOutPort(); + + retarder.InPort().Connect(nextRequest); + var outPort = retarder.OutPort(); + + var absTime = 0.SI<Second>(); + var dt = 0.SI<Second>(); + + // -------- + outPort.Initialize(100.SI<NewtonMeter>(), 125.RPMtoRad()); + outPort.Request(absTime, dt, 100.SI<NewtonMeter>(), 125.RPMtoRad()); + + Assert.AreEqual(125.RPMtoRad().Value(), nextRequest.AngularVelocity.Value(), Delta); + Assert.AreEqual(100 + 5.065, nextRequest.Torque.Value(), Delta); + } } } \ No newline at end of file