@@ -171,8 +171,8 @@ public class MSTSSteamLocomotive : MSTSLocomotive
171171 float BoosterEngineSpeedRpM;
172172 bool BoosterAirisLow = false;
173173 int BoosterEngineNumber;
174-
175- float SteamLocomotiveRetardingDynamicBrakeForceN = 0 ;
174+
175+ bool CounterPressureBrakingFitted = false ;
176176
177177 /// <summary>
178178 /// Grate limit of locomotive exceedeed?
@@ -1059,6 +1059,10 @@ public override void Parse(string lowercasetoken, STFReader stf)
10591059 IsSelectGeared = String.Compare(typeString2, "Select") == 0;
10601060 break;
10611061
1062+ case "engine(ortscounterpressurebraking":
1063+ CounterPressureBrakingFitted = stf.ReadBoolBlock(false);
1064+ break;
1065+
10621066 case "engine(ortsbattery(mode":
10631067 case "engine(ortsbattery(delay":
10641068 case "engine(ortsbattery(defaulton":
@@ -1107,6 +1111,7 @@ public override void Copy(MSTSWagon copy)
11071111 EjectorLargeSteamConsumptionLbpS = locoCopy.EjectorLargeSteamConsumptionLbpS;
11081112 ShovelMassKG = locoCopy.ShovelMassKG;
11091113 GearedTractiveEffortFactor = locoCopy.GearedTractiveEffortFactor;
1114+ CounterPressureBrakingFitted = locoCopy.CounterPressureBrakingFitted;
11101115 TractiveEffortFactor = locoCopy.TractiveEffortFactor;
11111116 MaxTenderFuelMassKG = locoCopy.MaxTenderFuelMassKG;
11121117 MaxLocoTenderWaterMassKG = locoCopy.MaxLocoTenderWaterMassKG;
@@ -2523,7 +2528,6 @@ public override void Update(float elapsedClockSeconds)
25232528
25242529 if (SteamEngines[i].AuxiliarySteamEngineType != SteamEngine.AuxiliarySteamEngineTypes.Booster)
25252530 {
2526- UpdateCounterPressure(elapsedClockSeconds, cutoff, i);
25272531 UpdateCylinders(elapsedClockSeconds, throttle, cutoff, absSpeedMpS, i);
25282532 }
25292533 else if (SteamEngines[i].AuxiliarySteamEngineType == SteamEngine.AuxiliarySteamEngineTypes.Booster) // Booster Engine
@@ -4876,58 +4880,9 @@ private void UpdateSuperHeat()
48764880 }
48774881
48784882 SuperheaterSteamUsageFactor = MathHelper.Clamp(SuperheaterSteamUsageFactor, 0.60f, SuperheaterSteamUsageFactor); // ensure factor does not go below 0.6, as this represents base steam consumption by the cylinders.
4879-
4880- }
4881-
4882- /// <summary>
4883- /// Calculate the counter pressure to be used by a locomotive as a braking effect
4884- /// To do this we first calculate the MEP air pressure of compressed air with each stroke, then we calculate the resulting "resisting" tractive force
4885- /// </summary>
4886- private void UpdateCounterPressure(float elapsedClockSeconds, float cutoff, int numberofengine)
4887- {
4888- SteamLocomotiveRetardingDynamicBrakeForceN = 0;
4889-
4890- float currentDynamicBrakeFraction = DynamicBrakePercent / 100;
4891-
4892- if (currentDynamicBrakeFraction > 0 && absSpeedMpS >0)
4893- {
4894- float CylinderVolumePoint_compression = (currentDynamicBrakeFraction * Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM)) + CylinderClearancePC;
4895- float CylinderVolumePoint_release = (Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) + 2 * CylinderClearancePC) - CylinderVolumePoint_compression;
4896-
4897- // Trace.TraceInformation("Vol-release {0} Vol-compression {1} Stroke {2}", CylinderVolumePoint_release, CylinderVolumePoint_compression, Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM));
4898-
4899- // Ratio of compression = stroke during compression = stroke @ start of compression / stroke and end of compression
4900- float CylinderRatio_compression = CylinderVolumePoint_compression / CylinderClearancePC;
4901- float CylinderRatio_release = CylinderVolumePoint_compression / (Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) + 2 * CylinderClearancePC);
4902-
4903- float CompMeanPressure_compressionAtmPSI = OneAtmospherePSI * CylinderRatio_compression * ((float)Math.Log(CylinderRatio_compression, 10) / (CylinderRatio_compression - 1.0f));
4904- float CompMeanPressure_releaseAtmPSI = CompMeanPressure_compressionAtmPSI * CylinderRatio_release * ((float)Math.Log(CylinderRatio_release) / (CylinderRatio_release - 1.0f));
4905-
4906- // Trace.TraceInformation("MEPcomp {0} Log {1} CompRatio {2}", CompMeanPressure_compressionAtmPSI, (float)Math.Log(CylinderRatio_compression), CylinderRatio_compression);
4907-
4908- float CylinderWork_compression_InLbs = CompMeanPressure_compressionAtmPSI * CylinderVolumePoint_compression;
4909- float CylinderWork_release_InLbs = CompMeanPressure_releaseAtmPSI * CylinderVolumePoint_release;
4910-
4911- // Trace.TraceInformation("Workc {0} Workr {1} Pc {2} Pr {3}", CylinderWork_compression_InLbs, CylinderWork_release_InLbs, CompMeanPressure_compressionAtmPSI, CompMeanPressure_releaseAtmPSI);
4912-
4913- float TotalWorkCounterPressure = CylinderWork_compression_InLbs + CylinderWork_release_InLbs;
4914-
4915- float CounterPressureMEP = TotalWorkCounterPressure / Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM);
4916-
4917- // Calculate tractive retarding force
4918- SteamLocomotiveRetardingDynamicBrakeForceN = N.FromLbf(CounterPressureMEP * Me.ToIn(SteamEngines[numberofengine].CylindersDiameterM) * Me.ToIn(SteamEngines[numberofengine].CylindersDiameterM) * Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) / Me.ToIn(SteamEngines[numberofengine].AttachedAxle.CogWheelRadiusM));
4919-
4920- // Trace.TraceInformation("CogRetardForce {0} throttle {1} MEP {2} Ratio-Comp {3} Ratio-Rel {4}", N.ToLbf(SteamLocomotiveRetardingDynamicBrakeForceN), throttle, CounterPressureMEP, CylinderRatio_compression, CylinderRatio_release);
4921- }
4922- else
4923- {
4924- SteamLocomotiveRetardingDynamicBrakeForceN = 0;
4925- }
4926-
4927-
49284883 }
49294884
4930- private void UpdateCylinders(float elapsedClockSeconds, float throttle, float cutoff, float absSpeedMpS, int numberofengine)
4885+ private void UpdateCylinders(float elapsedClockSeconds, float throttle, float cutoff, float absSpeedMpS, int numberofengine)
49314886 {
49324887 // Calculate speed of locomotive in wheel rpm - used to determine changes in performance based upon speed.
49334888 SteamEngines[numberofengine].DriveWheelRevRpS = absSpeedMpS / (2.0f * MathHelper.Pi * SteamEngines[numberofengine].AttachedAxle.WheelRadiusM);
@@ -6043,6 +5998,58 @@ private void UpdateCylinders(float elapsedClockSeconds, float throttle, float cu
60435998
60445999 SteamReleasePressure_AtmPSI = SteamEngines[numberofengine].Pressure_c_AtmPSI; // for steam and smoke effects
60456000
6001+
6002+ // Calculate the counter pressure to be used by a locomotive as a braking effect
6003+ // To do this we first calculate the MEP air pressure of compressed air with each stroke, then we calculate the resulting "resisting" tractive force
6004+
6005+ SteamEngines[numberofengine].CylinderCounterPressureBrakeForceN = 0;
6006+
6007+ float currentDynamicBrakeFraction = DynamicBrakePercent / 100;
6008+
6009+ if (currentDynamicBrakeFraction > 0 && absSpeedMpS > 0)
6010+ {
6011+ float CylinderVolumePoint_compression = (currentDynamicBrakeFraction * Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM)) + CylinderClearancePC;
6012+ float CylinderVolumePoint_release = (Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) + 2 * CylinderClearancePC) - CylinderVolumePoint_compression;
6013+
6014+ // Trace.TraceInformation("Vol-release {0} Vol-compression {1} Stroke {2}", CylinderVolumePoint_release, CylinderVolumePoint_compression, Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM));
6015+
6016+ // Ratio of compression = stroke during compression = stroke @ start of compression / stroke and end of compression
6017+ float CylinderRatio_compression = CylinderVolumePoint_compression / CylinderClearancePC;
6018+ float CylinderRatio_release = CylinderVolumePoint_compression / (Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) + 2 * CylinderClearancePC);
6019+
6020+ float CompMeanPressure_compressionAtmPSI = OneAtmospherePSI * CylinderRatio_compression * ((float)Math.Log(CylinderRatio_compression, 10) / (CylinderRatio_compression - 1.0f));
6021+ float CompMeanPressure_releaseAtmPSI = CompMeanPressure_compressionAtmPSI * CylinderRatio_release * ((float)Math.Log(CylinderRatio_release) / (CylinderRatio_release - 1.0f));
6022+
6023+ // Trace.TraceInformation("MEPcomp {0} Log {1} CompRatio {2}", CompMeanPressure_compressionAtmPSI, (float)Math.Log(CylinderRatio_compression), CylinderRatio_compression);
6024+
6025+ float CylinderWork_compression_InLbs = CompMeanPressure_compressionAtmPSI * CylinderVolumePoint_compression;
6026+ float CylinderWork_release_InLbs = CompMeanPressure_releaseAtmPSI * CylinderVolumePoint_release;
6027+
6028+ // Trace.TraceInformation("Workc {0} Workr {1} Pc {2} Pr {3}", CylinderWork_compression_InLbs, CylinderWork_release_InLbs, CompMeanPressure_compressionAtmPSI, CompMeanPressure_releaseAtmPSI);
6029+
6030+ float TotalWorkCounterPressure = CylinderWork_compression_InLbs + CylinderWork_release_InLbs;
6031+
6032+ float CounterPressureMEP = TotalWorkCounterPressure / Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM);
6033+
6034+ // Assume no impact of "return" stroke as air is being drawn into cylinder
6035+
6036+ // Calculate tractive retarding force
6037+ SteamEngines[numberofengine].CylinderCounterPressureBrakeForceN = N.FromLbf(CounterPressureMEP * Me.ToIn(SteamEngines[numberofengine].CylindersDiameterM) * Me.ToIn(SteamEngines[numberofengine].CylindersDiameterM) * Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) / Me.ToIn(SteamEngines[numberofengine].AttachedAxle.CogWheelRadiusM));
6038+
6039+ // Trace.TraceInformation("CogRetardForce {0} throttle {1} MEP {2} Ratio-Comp {3} Ratio-Rel {4}", N.ToLbf(SteamLocomotiveRetardingDynamicBrakeForceN), throttle, CounterPressureMEP, CylinderRatio_compression, CylinderRatio_release);
6040+ }
6041+ else
6042+ {
6043+ SteamEngines[numberofengine].CylinderCounterPressureBrakeForceN = 0;
6044+ }
6045+
6046+
6047+
6048+
6049+
6050+
6051+
6052+
60466053 }
60476054
60486055
@@ -6562,6 +6569,7 @@ private void UpdateSteamTractiveForce(float elapsedClockSeconds, float locomotiv
65626569 protected override void UpdateTractiveForce(float elapsedClockSeconds, float locomotivethrottle, float AbsSpeedMpS, float AbsWheelSpeedMpS)
65636570 {
65646571 TractiveForceN = 0; // reset tractiveforceN in preparation to calculating a new value
6572+ DynamicBrakeForceN = 0;
65656573 if (!Simulator.UseAdvancedAdhesion && Simulator.Settings.SimpleControlPhysics)
65666574 {
65676575 // Simple adhesion
@@ -6587,11 +6595,31 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
65876595 {
65886596 ApplyDirectionToTractiveForce(ref SteamEngines[i].RealTractiveForceN, i);
65896597
6590- TractiveForceN += SteamEngines[i].RealTractiveForceN;
6598+ TractiveForceN += SteamEngines[i].RealTractiveForceN + DynamicBrakeForceN ;
65916599
65926600 if (Simulator.UseAdvancedAdhesion && !Simulator.Settings.SimpleControlPhysics)
65936601 {
65946602 SteamEngines[i].AttachedAxle.DriveForceN = SteamEngines[i].RealTractiveForceN;
6603+
6604+ // Counter Pressure braking system
6605+
6606+ if (DynamicBrakePercent > 0 && CounterPressureBrakingFitted && absSpeedMpS > 0.1)
6607+ {
6608+ DynamicBrakeForceN += SteamEngines[i].CylinderCounterPressureBrakeForceN;
6609+ TractiveForceN -= (SpeedMpS > 0 ? 1 : SpeedMpS < 0 ? -1 : Direction == Direction.Reverse ? -1 : 1) * DynamicBrakeForceN;
6610+ SteamEngines[i].AttachedAxle.DriveForceN = SteamEngines[i].RealTractiveForceN;
6611+ }
6612+ else
6613+ {
6614+ DynamicBrakeForceN = 0;
6615+ }
6616+
6617+ if (DynamicBrakeForceN > 0)
6618+ {
6619+
6620+ SteamEngines[i].AttachedAxle.DriveForceN = DynamicBrakeForceN;
6621+ }
6622+
65956623 UpdateAxleDriveForce();
65966624
65976625 SteamEngines[i].DisplayTractiveForceN = SteamEngines[i].AverageTractiveForceN;
@@ -6641,25 +6669,12 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
66416669 MaxSpeedMpS = Me.FromMi(pS.FrompH(MaxLocoSpeedMpH)); // Note this is not the true max velocity of the locomotive, but the speed at which max HP is reached
66426670
66436671 // Set tractive force to zero if throttle is closed
6644- if (locomotivethrottle < 0.001)
6672+ if (locomotivethrottle < 0.001 && !CounterPressureBrakingFitted )
66456673 {
66466674 TractiveForceN = 0;
66476675 }
6648-
6649- // if (DynamicBrakePercent > 0 && DynamicBrake)
6650-
6651- if (DynamicBrakePercent > 0)
6652- {
6653- DynamicBrakeForceN = SteamLocomotiveRetardingDynamicBrakeForceN;
6654- }
6655- else
6656- {
6657- DynamicBrakeForceN = 0;
6658- }
6659-
66606676 }
66616677
6662-
66636678 /// <summary>
66646679 /// This function applies a sign to the motive force as a function of the direction of the train.
66656680 /// </summary>
@@ -8443,7 +8458,6 @@ public override string GetDebugStatus()
84438458 FormatStrings.mm);
84448459 }
84458460
8446-
84478461 if (SteamIsAuxTenderCoupled)
84488462 {
84498463 status.AppendFormat("{0}\t{1}\t{2}\t{3:N0}%\t{4}\t{5}\t\t{6:N0}%\t{7}\t{8}\t\t{9}\t{10}\t\t{11}\t{12:N0}\t{13}\t{14:N0}\n",
0 commit comments