Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS will be completely phased out by mid-2025. To see alternatives please check here

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

Merge pull request #355 in VECTO/vecto-sim from...

Merge pull request #355 in VECTO/vecto-sim from ~EMQUARIMA/vecto-sim:bugfix/VECTO-428-sum-of-time-shares-in-vsum-file to develop

* commit 'c6eb5bf9':
  simplify computation of time shares, use values directly from mod-data, without averaging over 3s beforehand.
  extend mod-data / sum-data integrity test to test for sum of time-shares
parents 674e5908 c6eb5bf9
No related branches found
No related tags found
No related merge requests found
......@@ -128,52 +128,65 @@ namespace TUGraz.VectoCore.OutputData
return self ?? defaultValue.SI<T>();
}
public static MeterPerSquareSecond AccelerationsPositive(this MeterPerSquareSecond[] acceleration3SecondAverage)
public static MeterPerSquareSecond AccelerationsPositive(this ModalDataContainer data)
{
try {
return acceleration3SecondAverage.Where(x => x > 0.125).Average();
} catch (NullReferenceException) {
return null;
}
return
data.GetValues<MeterPerSquareSecond>(ModalResultField.acc)
.Where(x => x < -0.125)
.DefaultIfEmpty(0.SI<MeterPerSquareSecond>())
.Average();
}
public static MeterPerSquareSecond AccelerationsNegative(this MeterPerSquareSecond[] acceleration3SecondAverage)
public static MeterPerSquareSecond AccelerationsNegative(this ModalDataContainer data)
{
if (acceleration3SecondAverage.Length > 0) {
return acceleration3SecondAverage.Where(x => x < -0.125).Average();
}
return null;
return
data.GetValues<MeterPerSquareSecond>(ModalResultField.acc)
.Where(x => x < -0.125)
.DefaultIfEmpty(0.SI<MeterPerSquareSecond>())
.Average();
}
public static Scalar AccelerationTimeShare(this MeterPerSquareSecond[] acceleration3SecondAverage)
public static Scalar AccelerationTimeShare(this ModalDataContainer data)
{
if (acceleration3SecondAverage.Length > 0) {
return 100.SI<Scalar>() * acceleration3SecondAverage.Count(x => x > 0.125) / acceleration3SecondAverage.Length;
}
return null;
var accelerationTimeShare = data.Data.Rows.Cast<DataRow>()
.Select(x => new {
a = x.Field<MeterPerSquareSecond>((int)ModalResultField.acc),
dt = x.Field<Second>((int)ModalResultField.simulationInterval)
})
.Where(x => x.a > 0.125).Sum(x => x.dt).DefaultIfNull(0);
return 100 * (accelerationTimeShare / data.Duration()).Cast<Scalar>();
}
public static Scalar DecelerationTimeShare(this MeterPerSquareSecond[] acceleration3SecondAverage)
public static Scalar DecelerationTimeShare(this ModalDataContainer data)
{
if (acceleration3SecondAverage.Length > 0) {
return 100.SI<Scalar>() * acceleration3SecondAverage.Count(x => x < -0.125) / acceleration3SecondAverage.Length;
}
return null;
var decelerationTimeShare = data.Data.Rows.Cast<DataRow>()
.Select(x => new {
a = x.Field<MeterPerSquareSecond>((int)ModalResultField.acc),
dt = x.Field<Second>((int)ModalResultField.simulationInterval)
})
.Where(x => x.a < -0.125).Sum(x => x.dt).DefaultIfNull(0);
return 100 * (decelerationTimeShare / data.Duration()).Cast<Scalar>();
}
public static Scalar CruiseTimeShare(this MeterPerSquareSecond[] acceleration3SecondAverage)
public static Scalar CruiseTimeShare(this ModalDataContainer data)
{
if (acceleration3SecondAverage.Length > 0) {
return 100.SI<Scalar>() * acceleration3SecondAverage.Count(x => x.IsBetween(-0.125, 0.125)) /
acceleration3SecondAverage.Length;
}
return null;
var cruiseTime = data.Data.Rows.Cast<DataRow>()
.Select(x => new {
v = x.Field<MeterPerSecond>((int)ModalResultField.v_act),
a = x.Field<MeterPerSquareSecond>((int)ModalResultField.acc),
dt = x.Field<Second>((int)ModalResultField.simulationInterval)
})
.Where(x => x.v >= 0.1 && x.a.IsBetween(-0.125, 0.125)).Sum(x => x.dt).DefaultIfNull(0);
return 100 * (cruiseTime / data.Duration()).Cast<Scalar>();
}
public static Scalar StopTimeShare(this IModalDataContainer data)
public static Scalar StopTimeShare(this ModalDataContainer data)
{
var stopTime = data.GetValues<MeterPerSecond>(ModalResultField.v_act)
.Zip(data.SimulationIntervals(), (v, dt) => new { v, dt })
var stopTime = data.Data.Rows.Cast<DataRow>()
.Select(x => new {
v = x.Field<MeterPerSecond>((int)ModalResultField.v_act),
dt = x.Field<Second>((int)ModalResultField.simulationInterval)
})
.Where(x => x.v < 0.1).Sum(x => x.dt) ?? 0.SI<Second>();
return 100 * (stopTime / data.Duration()).Cast<Scalar>();
}
......@@ -306,21 +319,6 @@ namespace TUGraz.VectoCore.OutputData
return data.TimeIntegral<WattSecond>(ModalResultField.P_eng_fcmap, x => x < 0);
}
//public static Watt PowerBrake(this IModalDataContainer data)
//{
// return data.TimeIntegral<WattSecond>(ModalResultField.P_brake_loss) / data.Duration();
//}
//public static Watt PowerAngle(this IModalDataContainer data)
//{
// return data.TimeIntegral<WattSecond>(ModalResultField.P_angle_loss) / data.Duration();
//}
//public static Watt PowerTorqueConverter(this IModalDataContainer data)
//{
// return data.TimeIntegral<WattSecond>(ModalResultField.P_TC_loss) / data.Duration();
//}
public static Watt PowerWheelPositive(this IModalDataContainer data)
{
return data.TimeIntegral<WattSecond>(ModalResultField.P_wheel_in, x => x > 0) / data.Duration();
......@@ -416,30 +414,7 @@ namespace TUGraz.VectoCore.OutputData
return data.TimeIntegral<Kilogram>(ModalResultField.FCMap) / distance;
}
//public static Watt EnginePowerNegativeAverage(this IModalDataContainer data)
//{
// var simulationIntervals = data.GetValues<Second>(ModalResultField.simulationInterval);
// var values = data.GetValues<Watt>(ModalResultField.P_eng_out)
// .Zip(simulationIntervals, (value, dt) => new { Dt = dt, Value = value * dt })
// .Where(v => v.Value < 0).ToList();
// if (values.Any()) {
// return values.Sum(v => v.Value) / values.Sum(v => v.Dt);
// }
// return 0.SI<Watt>();
//}
//public static Watt EnginePowerPositiveAverage(this IModalDataContainer data)
//{
// var simulationIntervals = data.GetValues<Second>(ModalResultField.simulationInterval);
// var values = data.GetValues<Watt>(ModalResultField.P_eng_out)
// .Zip(simulationIntervals, (value, dt) => new { Dt = dt, Value = value * dt })
// .Where(v => v.Value > 0).ToList();
// if (values.Any()) {
// return values.Sum(v => v.Value) / values.Sum(v => v.Dt);
// }
// return 0.SI<Watt>();
//}
public static Watt TotalPowerEnginePositiveAverage(this IModalDataContainer data)
{
var simulationIntervals = data.GetValues<Second>(ModalResultField.simulationInterval);
......@@ -475,57 +450,6 @@ namespace TUGraz.VectoCore.OutputData
return sum;
}
public static MeterPerSquareSecond[] AccelerationPer3Seconds(this IModalDataContainer data)
{
var accs = new List<MeterPerSquareSecond>(1000);
var accelerationAverages = AccelerationPerSecond(data).ToList();
if (accelerationAverages.Count >= 3) {
var runningAverage = (accelerationAverages[0] + accelerationAverages[1] + accelerationAverages[2]) / 3.0;
accs.Add(runningAverage);
for (var i = 2; i < accelerationAverages.Count - 1; i++) {
runningAverage -= accelerationAverages[i - 2] / 3.0;
runningAverage += accelerationAverages[i + 1] / 3.0;
accs.Add(runningAverage);
}
}
return accs.ToArray();
}
/// <summary>
/// Calculates the average acceleration for whole seconds.
/// </summary>
private static IEnumerable<MeterPerSquareSecond> AccelerationPerSecond(IModalDataContainer data)
{
var dtSum = 0.SI<Second>();
var accAvg = 0.SI<MeterPerSecond>();
var accValues = data.GetValues<MeterPerSquareSecond>(ModalResultField.acc);
foreach (
var value in accValues.Zip(SimulationIntervals(data), (acc, dt) => new { acc, dt }).Where(v => v.acc != null)) {
var dt = value.dt;
var acc = value.acc;
while (dtSum + dt >= 1) {
var diffDt = 1.SI<Second>() - dtSum;
yield return (accAvg + acc * diffDt) / 1.SI<Second>();
dt -= diffDt;
dtSum = 0.SI<Second>();
accAvg = 0.SI<MeterPerSecond>();
}
if (dt > 0) {
accAvg += acc * dt;
dtSum += dt;
}
}
// return remaining data. acts like extrapolation to next whole second.
if (dtSum > 0) {
yield return accAvg / 1.SI<Second>();
}
}
}
}
\ No newline at end of file
......@@ -174,7 +174,8 @@ namespace TUGraz.VectoCore.OutputData
row[LOADING] = vehicleLoading;
row[VOLUME] = cargoVolume;
row[TIME] = modData.Duration();
var totalTime = modData.Duration();
row[TIME] = totalTime;
var distance = modData.Distance();
if (distance != null) {
......@@ -282,26 +283,34 @@ namespace TUGraz.VectoCore.OutputData
row[E_ROLL] = modData.WorkRollingResistance().ConvertTo().Kilo.Watt.Hour;
row[E_GRAD] = modData.WorkRoadGradientResistance().ConvertTo().Kilo.Watt.Hour;
var acc = modData.AccelerationPer3Seconds();
//var acc = modData.AccelerationPer3Seconds();
row[ACC] = modData.AccelerationAverage();
row[ACC_POS] = acc.AccelerationsPositive();
row[ACC_NEG] = acc.AccelerationsNegative();
var accTimeShare = acc.AccelerationTimeShare();
var modal = modData as ModalDataContainer;
if (modal == null) {
Log.Error("unknown modal data container!");
return;
}
row[ACC_POS] = modal.AccelerationsPositive();
row[ACC_NEG] = modal.AccelerationsNegative();
var accTimeShare = modal.AccelerationTimeShare();
row[ACC_TIMESHARE] = accTimeShare;
var decTimeShare = acc.DecelerationTimeShare();
var decTimeShare = modal.DecelerationTimeShare();
row[DEC_TIMESHARE] = decTimeShare;
var cruiseTimeShare = acc.CruiseTimeShare();
var cruiseTimeShare = modal.CruiseTimeShare();
row[CRUISE_TIMESHARE] = cruiseTimeShare;
row[STOP_TIMESHARE] = modData.StopTimeShare();
var stopTimeShare = modal.StopTimeShare();
row[STOP_TIMESHARE] = stopTimeShare;
if (accTimeShare != null && decTimeShare != null && cruiseTimeShare != null) {
var shareSum = accTimeShare + decTimeShare + cruiseTimeShare;
var shareSum = accTimeShare + decTimeShare + cruiseTimeShare + stopTimeShare;
if (!shareSum.IsEqual(100)) {
Log.Error(
"Sumfile Error: driving behavior timeshares must sum up to 100%: acc: {0}%, dec: {1}%, cruise: {2}%, sum: {3}%",
"Sumfile Error: driving behavior timeshares must sum up to 100%: acc: {0}%, dec: {1}%, cruise: {2}%, stop: {3}%, sum: {4}%",
accTimeShare.ToOutputFormat(1, null, false), decTimeShare.ToOutputFormat(1, null, false),
cruiseTimeShare.ToOutputFormat(1, null, false), shareSum.ToOutputFormat(1, null, false));
cruiseTimeShare.ToOutputFormat(1, null, false), stopTimeShare.ToOutputFormat(1, null, false),
shareSum.ToOutputFormat(1, null, false));
}
}
}
......
......@@ -57,6 +57,8 @@ namespace TUGraz.VectoCore.Tests.Reports
[TestFixture]
public class ModDataTest
{
[TestCase()]
public void ModDataIntegritySimpleTest()
{
......@@ -208,6 +210,14 @@ namespace TUGraz.VectoCore.Tests.Reports
Assert.AreEqual(fcPerLoad, fcPer100km / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}",
inputFile, cycle, loading);
}
var stopTimeShare = ((SI)row[SummaryDataContainer.STOP_TIMESHARE]).Value();
var accTimeShare = ((SI)row[SummaryDataContainer.ACC_TIMESHARE]).Value();
var decTimeShare = ((SI)row[SummaryDataContainer.DEC_TIMESHARE]).Value();
var cruiseTimeShare = ((SI)row[SummaryDataContainer.CRUISE_TIMESHARE]).Value();
Assert.AreEqual(100, stopTimeShare + accTimeShare + decTimeShare + cruiseTimeShare, 1e-3,
"input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading);
}
}
......
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