added valves display

This commit is contained in:
maxwes08
2026-05-06 14:05:37 +02:00
parent d6b1d214f5
commit bc4e077924
4 changed files with 103 additions and 29 deletions

View File

@@ -17,17 +17,19 @@ namespace FluidSim.Core
// ---- Exhaust valve ---- // ---- Exhaust valve ----
private double exhMaxOrificeArea; private double exhMaxOrificeArea;
private double exhValveOpenStart = 120.0 * Math.PI / 180.0; // 120° (EVO) private double exhValveOpenStart = 130.0 * Math.PI / 180.0;
private double exhValveOpenEnd = 480.0 * Math.PI / 180.0; // 480° (EVC) private double exhValveOpenEnd = 390.0 * Math.PI / 180.0;
private double exhValveRampWidth = 30.0 * Math.PI / 180.0; private double exhValveRampWidth = 30.0 * Math.PI / 180.0;
public double ExhaustOrificeArea => ExhaustValveLift() * exhMaxOrificeArea; public double ExhaustOrificeArea => ExhaustValveLift() * exhMaxOrificeArea;
public double ExhaustValveLiftCurrent => ExhaustValveLift();
// ---- Intake valve ---- // ---- Intake valve ----
private double intMaxOrificeArea; private double intMaxOrificeArea;
private double intValveOpenStart = 380.0 * Math.PI / 180.0; // 380° (IVO) private double intValveOpenStart = 340.0 * Math.PI / 180.0;
private double intValveOpenEnd = 560.0 * Math.PI / 180.0; // 560° (IVC) private double intValveOpenEnd = 600.0 * Math.PI / 180.0;
private double intValveRampWidth = 30.0 * Math.PI / 180.0; private double intValveRampWidth = 30.0 * Math.PI / 180.0;
public double IntakeOrificeArea => IntakeValveLift() * intMaxOrificeArea; public double IntakeOrificeArea => IntakeValveLift() * intMaxOrificeArea;
public double IntakeValveLiftCurrent => IntakeValveLift();
// ---- Combustion ---- // ---- Combustion ----
public double TargetPeakPressure { get; set; } = 50.0 * 101325.0; public double TargetPeakPressure { get; set; } = 50.0 * 101325.0;
@@ -70,8 +72,8 @@ namespace FluidSim.Core
this.stroke = stroke; this.stroke = stroke;
conRodLength = 2.0 * stroke; conRodLength = 2.0 * stroke;
this.compressionRatio = compressionRatio; this.compressionRatio = compressionRatio;
exhMaxOrificeArea = exhPipeArea; exhMaxOrificeArea = exhPipeArea * 0.5;
intMaxOrificeArea = intPipeArea; intMaxOrificeArea = intPipeArea * 0.5;
pistonArea = Math.PI / 4.0 * bore * bore; pistonArea = Math.PI / 4.0 * bore * bore;
V_disp = pistonArea * stroke; V_disp = pistonArea * stroke;

46
Components/Nozzleflow.cs Normal file
View File

@@ -0,0 +1,46 @@
using System;
namespace FluidSim.Components
{
public static class NozzleFlow
{
/// <summary>
/// Computes the nozzleexit primitive state and mass flow rate from a
/// volume to a pipe, using isentropic relations. Follows ensim4's flow() logic.
/// </summary>
public static void Compute(double Pt_high, double Tt_high,
double P_low, double gamma, double R, double area,
out double rhoExit, out double uExit,
out double pExit, out double mdot)
{
double gm1 = gamma - 1.0;
double Pt_over_Ps = Pt_high / P_low;
// Mach number (subsonic, clamped to 1)
double M = Math.Sqrt(Math.Max(0.0,
(2.0 / gm1) * (Math.Pow(Pt_over_Ps, gm1 / gamma) - 1.0)));
if (M > 1.0) M = 1.0;
double T_star = Tt_high / (1.0 + 0.5 * gm1 * M * M);
double a_star = Math.Sqrt(gamma * R * T_star);
double u_star = M * a_star;
pExit = Pt_high * Math.Pow(1.0 + 0.5 * gm1 * M * M, -gamma / gm1);
rhoExit = pExit / (R * T_star);
uExit = u_star; // positive away from highpressure side
mdot = rhoExit * uExit * area;
}
/// <summary>
/// Ambient cell for nonreflecting open end (ensim4 calc_ambient_cell).
/// </summary>
public static void ComputeAmbientCell(double rhoInt, double uInt, double pInt,
double pAmbient, double gamma,
out double rhoAmb, out double uAmb,
out double pAmb)
{
pAmb = pAmbient;
uAmb = uInt;
rhoAmb = rhoInt * Math.Pow(pAmb / pInt, 1.0 / gamma);
}
}
}

View File

@@ -25,7 +25,7 @@ public class Program
// Throttle smoothing // Throttle smoothing
private static double targetThrottle = 0.0; // 1.0 when W is pressed, 0.0 otherwise private static double targetThrottle = 0.0; // 1.0 when W is pressed, 0.0 otherwise
private static double currentThrottle = 0.0; private static double currentThrottle = 0.0;
private const double ThrottleSmoothing = 40.0; // rate of change private const double ThrottleSmoothing = 20.0; // rate of change
private static volatile bool running = true; private static volatile bool running = true;

View File

@@ -31,7 +31,7 @@ namespace FluidSim.Core
private const int LogInterval = 1000; private const int LogInterval = 1000;
public double Throttle { get; set; } = 0.15; public double Throttle { get; set; } = 0.15;
private const double FullLoadPeakPressure = 60.0 * Units.bar; private const double FullLoadPeakPressure = 140.0 * Units.bar;
public override void Initialize(int sampleRate) public override void Initialize(int sampleRate)
{ {
@@ -41,29 +41,29 @@ namespace FluidSim.Core
crankshaft = new Crankshaft(initialRPM: 2000.0) crankshaft = new Crankshaft(initialRPM: 2000.0)
{ {
Inertia = 0.05, Inertia = 0.05,
FrictionConstant = 0.5, FrictionConstant = 0.2,
FrictionViscous = 0.01 FrictionViscous = 0.025
}; };
// Exhaust pipe (longer, larger) // Exhaust pipe (longer, larger)
double exhLength = 1; double exhLength = 0.5;
double exhRadius = 0.02; double exhRadius = 1.5 * Units.cm;
exhPipeArea = Math.PI * exhRadius * exhRadius; exhPipeArea = Math.PI * exhRadius * exhRadius;
exhaustPipe = new Pipe1D(exhLength, exhPipeArea, sampleRate, forcedCellCount: 100); exhaustPipe = new Pipe1D(exhLength, exhPipeArea, sampleRate, forcedCellCount: 30);
exhaustPipe.SetUniformState(1.225, 0.0, AmbientPressure); exhaustPipe.SetUniformState(1.225, 0.0, AmbientPressure);
exhaustPipe.DampingMultiplier = 0.0; exhaustPipe.DampingMultiplier = 0.0;
exhaustPipe.EnergyRelaxationRate = 100.0f; exhaustPipe.EnergyRelaxationRate = 100.0f;
// Intake pipe (shorter, narrower) // Intake pipe (shorter, narrower)
double intLength = 1; double intLength = 0.1;
double intRadius = 0.01; double intRadius = 1 * Units.cm;
intPipeArea = Math.PI * intRadius * intRadius; intPipeArea = Math.PI * intRadius * intRadius;
intakePipe = new Pipe1D(intLength, intPipeArea, sampleRate, forcedCellCount: 50); intakePipe = new Pipe1D(intLength, intPipeArea, sampleRate, forcedCellCount: 10);
intakePipe.SetUniformState(1.225, 0.0, AmbientPressure); intakePipe.SetUniformState(1.225, 0.0, AmbientPressure);
// Cylinder (starts at BDC, fresh charge) // Cylinder (starts at BDC, fresh charge)
engineCyl = new EngineCylinder(crankshaft, engineCyl = new EngineCylinder(crankshaft,
bore: 0.065, stroke: 0.0565, compressionRatio: 8.0, bore: 56 * Units.mm, stroke: 57 * Units.mm, compressionRatio: 9.5,
exhPipeArea: exhPipeArea, intPipeArea: intPipeArea, sampleRate: sampleRate); exhPipeArea: exhPipeArea, intPipeArea: intPipeArea, sampleRate: sampleRate);
engineCyl.ignition = true; engineCyl.ignition = true;
@@ -107,7 +107,9 @@ namespace FluidSim.Core
public override float Process() public override float Process()
{ {
double throttle = Math.Clamp(Throttle, 0.2, 1.0); double idleThrottle = 0.1;
if (crankshaft.AngularVelocity < 80) idleThrottle = 0.2;
double throttle = Math.Clamp(Throttle, idleThrottle, 1.0);
double targetPressure = throttle * FullLoadPeakPressure; double targetPressure = throttle * FullLoadPeakPressure;
engineCyl.TargetPeakPressure = targetPressure; engineCyl.TargetPeakPressure = targetPressure;
@@ -251,12 +253,36 @@ namespace FluidSim.Core
}; };
target.Draw(pistonRect); target.Draw(pistonRect);
// ---------- NEW: Valve lift indicators ----------
float barWidth = 30f;
float barHeight = 10f;
float exhLift = (float)engineCyl.ExhaustValveLiftCurrent;
float intLift = (float)engineCyl.IntakeValveLiftCurrent;
// Exhaust valve indicator (right side of cylinder)
var exhBar = new RectangleShape(new Vector2f(barWidth, barHeight))
{
Position = new Vector2f(cylRect.Position.X + cylW - 10,
cylRect.Position.Y - 20 - exhLift * 20),
FillColor = new Color(200, 200, 200)
};
target.Draw(exhBar);
// Intake valve indicator (left side of cylinder)
var intBar = new RectangleShape(new Vector2f(barWidth, barHeight))
{
Position = new Vector2f(cylRect.Position.X - 20,
cylRect.Position.Y - 20 - intLift * 20),
FillColor = new Color(200, 200, 200)
};
target.Draw(intBar);
// ---- Exhaust pipe (rightwards) ---- // ---- Exhaust pipe (rightwards) ----
DrawPipe(target, exhaustPipe, startX: 280f, endX: winW - 60f, centerY, DrawPipe(target, exhaustPipe, startX: 280f, endX: winW - 60f, centerY + 10 - cylRect.Size.Y / 2,
T_ambient, T_hot, T_cold, R, NormaliseTemperature, true); T_ambient, T_hot, T_cold, R, NormaliseTemperature, true);
// ---- Intake pipe (leftwards) ---- // ---- Intake pipe (leftwards) ----
DrawPipe(target, intakePipe, startX: 200f, endX: 20f, centerY, DrawPipe(target, intakePipe, startX: 200f, endX: 20f, centerY + 10 - cylRect.Size.Y / 2,
T_ambient, T_hot, T_cold, R, NormaliseTemperature, false); T_ambient, T_hot, T_cold, R, NormaliseTemperature, false);
} }
@@ -280,7 +306,7 @@ namespace FluidSim.Core
double rho = pipe.GetCellDensity(i); double rho = pipe.GetCellDensity(i);
double T = p / (rho * R); double T = p / (rho * R);
float r = baseRadius * 0.3f * (float)(1.0 + (p - ambPress) / ambPress); float r = baseRadius * 0.2f * (float)(1.0 + (p - ambPress) / ambPress);
if (r < 2f) r = 2f; if (r < 2f) r = 2f;
float tn = normaliseTemp(T); float tn = normaliseTemp(T);