added 4 cyl

This commit is contained in:
max
2026-05-08 00:38:26 +02:00
parent b7a40217db
commit f275937abb
7 changed files with 374 additions and 66 deletions

View File

@@ -46,9 +46,7 @@ namespace FluidSim.Components
public double FuelLowerHeatingValue { get; set; } = 44e6;
// Cycletocycle randomness
/// <summary>Fractional variation in fuel energy (±). 0.05 = ±5%.</summary>
public double EnergyVariationFraction { get; set; } = 0.05;
/// <summary>Probability of a misfire (01).</summary>
public double MisfireProbability { get; set; } = 0.01;
// Heat loss
@@ -56,7 +54,14 @@ namespace FluidSim.Components
public double HeatTransferCoefficient { get; set; } = 100.0;
public double AmbientTemperature { get; set; } = 300.0;
// State
// ---- Multicylinder support ----
/// <summary>
/// Phase offset (radians) added to the crankshaft angle for this cylinder.
/// Used for multicylinder engines; set to 0 for singlecylinder.
/// </summary>
public double PhaseOffset { get; set; } = 0.0;
// State (public for drawing)
public double Volume => cylinderVolume;
public double Pressure => (Gamma - 1.0) * cylinderEnergy / Math.Max(cylinderVolume, 1e-12);
public double Temperature => Pressure / Math.Max(Density * GasConstant, 1e-12);
@@ -75,8 +80,7 @@ namespace FluidSim.Components
private bool combustionActive;
private bool fuelInjected;
// percycle randomness
private double _energyFactor = 1.0; // applied to FuelLowerHeatingValue this cycle
private double _energyFactor = 1.0;
private readonly Random _random = new Random();
private const double Gamma = 1.4;
@@ -115,7 +119,10 @@ namespace FluidSim.Components
private double clearanceVolume => SweptVolume / (CompressionRatio - 1.0);
private double CrankRadius => Stroke / 2.0;
private double Obliquity => CrankRadius / ConRodLength;
private double CrankDeg => (Crankshaft.CrankAngle % (4.0 * Math.PI)) * 180.0 / Math.PI % 720.0;
// Offset-aware crank angle in degrees
private double CrankDeg =>
((Crankshaft.CrankAngle + PhaseOffset) % (4.0 * Math.PI)) * 180.0 / Math.PI % 720.0;
public double ComputeVolume(double thetaRad)
{
@@ -174,7 +181,9 @@ namespace FluidSim.Components
public void PreStep(double dt)
{
double prevVolume = cylinderVolume;
double crankAngleRad = Crankshaft.CrankAngle;
// ----- Use phaseoffset crank angle for this cylinder -----
double crankAngleRad = Crankshaft.CrankAngle + PhaseOffset;
cylinderVolume = ComputeVolume(crankAngleRad);
double dV = cylinderVolume - prevVolume;
@@ -191,7 +200,9 @@ namespace FluidSim.Components
cylinderEnergy -= Pressure * dV;
double prevDeg = Crankshaft.PreviousAngle * 180.0 / Math.PI % 720.0;
// Also use offset angle for event detection
double crankshaftPrevAngle = Crankshaft.PreviousAngle;
double prevDeg = (crankshaftPrevAngle + PhaseOffset) * 180.0 / Math.PI % 720.0;
double currDeg = crankAngleRad * 180.0 / Math.PI % 720.0;
// ----- Intake closing: capture trapped air mass and compute fuel -----
@@ -202,7 +213,7 @@ namespace FluidSim.Components
fuelInjected = true;
}
// ----- Spark ignition (once per cycle, with misfire chance) -----
// ----- Spark ignition -----
double sparkAngle = 0.0 - SparkAdvance;
if (sparkAngle < 0) sparkAngle += 720.0;
@@ -210,19 +221,15 @@ namespace FluidSim.Components
(prevDeg > sparkAngle + 360.0 && currDeg < sparkAngle);
if (crossedSpark && !combustionActive && fuelInjected)
{
// Decide misfire
bool misfire = _random.NextDouble() < MisfireProbability;
if (misfire)
{
combustionActive = false; // no combustion this cycle
// fuel is not burned will remain in cylinder and eventually exit as unburned mixture
combustionActive = false;
}
else
{
combustionActive = true;
burnFraction = 0.0;
// Energy variation factor for this cycle
double range = EnergyVariationFraction;
_energyFactor = 1.0 + range * (2.0 * _random.NextDouble() - 1.0);
}
@@ -239,7 +246,6 @@ namespace FluidSim.Components
{
newFraction = 1.0;
combustionActive = false;
// All gas becomes exhaust
double totalMass = _airMass + _exhaustMass;
_airMass = 0.0;
_exhaustMass = totalMass;
@@ -255,7 +261,7 @@ namespace FluidSim.Components
}
}
// ----- Heat loss to cylinder walls -----
// ----- Heat loss -----
double dQ_loss = HeatTransferCoefficient * CylinderWallArea *
(Temperature - AmbientTemperature) * dt;
cylinderEnergy -= dQ_loss;