added two stroke scenario with vehicle

This commit is contained in:
max
2026-06-09 21:35:48 +02:00
parent ac2eab6f83
commit 1240ebc33d
8 changed files with 901 additions and 232 deletions

View File

@@ -4,33 +4,30 @@ namespace FluidSim.Components
{
public class Crankshaft
{
public float AngularVelocity; // rad/s
public float CrankAngle; // rad, 0 … 4π
public float AngularVelocity;
public float CrankAngle;
public float PreviousAngle;
public float Inertia = 0.2f; // kg·m²
public float FrictionConstant; // N·m
public float FrictionViscous; // N·m per rad/s
public float Inertia = 0.2f;
public float FrictionConstant;
public float FrictionViscous;
public float LastNetTorque { get; private set; }
public float AveragePower { get; private set; } // smoothed, watts
public float AverageTorque { get; private set; } // smoothed, Nm
public float AveragePower { get; private set; }
public float AverageTorque { get; private set; }
private float externalTorque;
private float _loadTorque; // external brake torque (Nm)
private float _loadTorque;
// Power averaging buffer
private readonly float[] _powerBuffer;
private int _powerBufIdx;
private int _powerBufCount;
private int _powerBufIdx, _powerBufCount;
private float _powerBufSum;
// Torque averaging buffer (same size as power buffer)
private readonly float[] _torqueBuffer;
private int _torqueBufIdx;
private int _torqueBufCount;
private int _torqueBufIdx, _torqueBufCount;
private float _torqueBufSum;
/// <summary>Engine cycle length in radians. 4π = fourstroke, 2π = twostroke.</summary>
public float CycleLength { get; set; } = 4f * MathF.PI;
public Crankshaft(float initialRPM = 400f)
{
AngularVelocity = initialRPM * 2f * MathF.PI / 60f;
@@ -43,9 +40,13 @@ namespace FluidSim.Components
public void AddTorque(float torque) => externalTorque += torque;
public void SetLoadTorque(float torque)
public void SetLoadTorque(float torque) => _loadTorque = Math.Max(torque, 0f);
private float _effectiveInertia; // if >0, overrides Inertia
public void SetEffectiveInertia(float inertia)
{
_loadTorque = Math.Max(torque, 0f);
_effectiveInertia = inertia;
}
public void Step(float dt)
@@ -57,51 +58,40 @@ namespace FluidSim.Components
PreviousAngle = CrankAngle;
// Internal friction torque
float friction = FrictionConstant * MathF.Sign(AngularVelocity)
+ FrictionViscous * AngularVelocity;
// Net torque from gas pressure minus friction (used for power/torque display)
float netTorque = externalTorque - friction;
LastNetTorque = netTorque;
// Total torque after subtracting external load (brake)
float totalNetTorque = netTorque - _loadTorque;
float alpha = totalNetTorque / Inertia;
float currentInertia = _effectiveInertia > 0f ? _effectiveInertia : Inertia;
float alpha = totalNetTorque / currentInertia;
AngularVelocity += alpha * dt;
if (AngularVelocity < 0f) AngularVelocity = 0f;
CrankAngle += AngularVelocity * dt;
if (CrankAngle >= 4f * MathF.PI)
CrankAngle -= 4f * MathF.PI;
if (CrankAngle >= CycleLength)
CrankAngle -= CycleLength;
else if (CrankAngle < 0f)
CrankAngle += 4f * MathF.PI;
CrankAngle += CycleLength;
// ---- Power averaging ----
// Power averaging
float instantPower = netTorque * AngularVelocity;
if (_powerBufCount == _powerBuffer.Length)
{
_powerBufSum -= _powerBuffer[_powerBufIdx];
}
else
{
_powerBufCount++;
}
_powerBuffer[_powerBufIdx] = instantPower;
_powerBufSum += instantPower;
_powerBufIdx = (_powerBufIdx + 1) % _powerBuffer.Length;
AveragePower = _powerBufSum / _powerBufCount;
// ---- Torque averaging ----
// Torque averaging
if (_torqueBufCount == _torqueBuffer.Length)
{
_torqueBufSum -= _torqueBuffer[_torqueBufIdx];
}
else
{
_torqueBufCount++;
}
_torqueBuffer[_torqueBufIdx] = netTorque;
_torqueBufSum += netTorque;
_torqueBufIdx = (_torqueBufIdx + 1) % _torqueBuffer.Length;