From bc4e077924336191cfd322a305cf3e593af7b6fe Mon Sep 17 00:00:00 2001 From: maxwes08 Date: Wed, 6 May 2026 14:05:37 +0200 Subject: [PATCH] added valves display --- Components/EngineCylinder.cs | 14 ++++---- Components/Nozzleflow.cs | 46 ++++++++++++++++++++++++ Program.cs | 2 +- Scenarios/EngineScenario.cs | 70 ++++++++++++++++++++++++------------ 4 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 Components/Nozzleflow.cs diff --git a/Components/EngineCylinder.cs b/Components/EngineCylinder.cs index 645fa29..348aecd 100644 --- a/Components/EngineCylinder.cs +++ b/Components/EngineCylinder.cs @@ -17,17 +17,19 @@ namespace FluidSim.Core // ---- Exhaust valve ---- private double exhMaxOrificeArea; - private double exhValveOpenStart = 120.0 * Math.PI / 180.0; // 120° (EVO) - private double exhValveOpenEnd = 480.0 * Math.PI / 180.0; // 480° (EVC) + private double exhValveOpenStart = 130.0 * Math.PI / 180.0; + private double exhValveOpenEnd = 390.0 * Math.PI / 180.0; private double exhValveRampWidth = 30.0 * Math.PI / 180.0; public double ExhaustOrificeArea => ExhaustValveLift() * exhMaxOrificeArea; + public double ExhaustValveLiftCurrent => ExhaustValveLift(); // ---- Intake valve ---- private double intMaxOrificeArea; - private double intValveOpenStart = 380.0 * Math.PI / 180.0; // 380° (IVO) - private double intValveOpenEnd = 560.0 * Math.PI / 180.0; // 560° (IVC) + private double intValveOpenStart = 340.0 * Math.PI / 180.0; + private double intValveOpenEnd = 600.0 * Math.PI / 180.0; private double intValveRampWidth = 30.0 * Math.PI / 180.0; public double IntakeOrificeArea => IntakeValveLift() * intMaxOrificeArea; + public double IntakeValveLiftCurrent => IntakeValveLift(); // ---- Combustion ---- public double TargetPeakPressure { get; set; } = 50.0 * 101325.0; @@ -70,8 +72,8 @@ namespace FluidSim.Core this.stroke = stroke; conRodLength = 2.0 * stroke; this.compressionRatio = compressionRatio; - exhMaxOrificeArea = exhPipeArea; - intMaxOrificeArea = intPipeArea; + exhMaxOrificeArea = exhPipeArea * 0.5; + intMaxOrificeArea = intPipeArea * 0.5; pistonArea = Math.PI / 4.0 * bore * bore; V_disp = pistonArea * stroke; diff --git a/Components/Nozzleflow.cs b/Components/Nozzleflow.cs new file mode 100644 index 0000000..a365f71 --- /dev/null +++ b/Components/Nozzleflow.cs @@ -0,0 +1,46 @@ +using System; + +namespace FluidSim.Components +{ + public static class NozzleFlow + { + /// + /// Computes the nozzle‑exit primitive state and mass flow rate from a + /// volume to a pipe, using isentropic relations. Follows ensim4's flow() logic. + /// + 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 high‑pressure side + mdot = rhoExit * uExit * area; + } + + /// + /// Ambient cell for non‑reflecting open end (ensim4 calc_ambient_cell). + /// + 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); + } + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 278e544..94ffa98 100644 --- a/Program.cs +++ b/Program.cs @@ -25,7 +25,7 @@ public class Program // Throttle smoothing private static double targetThrottle = 0.0; // 1.0 when W is pressed, 0.0 otherwise 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; diff --git a/Scenarios/EngineScenario.cs b/Scenarios/EngineScenario.cs index c0f513f..57f43d3 100644 --- a/Scenarios/EngineScenario.cs +++ b/Scenarios/EngineScenario.cs @@ -31,7 +31,7 @@ namespace FluidSim.Core private const int LogInterval = 1000; 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) { @@ -41,29 +41,29 @@ namespace FluidSim.Core crankshaft = new Crankshaft(initialRPM: 2000.0) { Inertia = 0.05, - FrictionConstant = 0.5, - FrictionViscous = 0.01 + FrictionConstant = 0.2, + FrictionViscous = 0.025 }; // Exhaust pipe (longer, larger) - double exhLength = 1; - double exhRadius = 0.02; + double exhLength = 0.5; + double exhRadius = 1.5 * Units.cm; 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.DampingMultiplier = 0.0; exhaustPipe.EnergyRelaxationRate = 100.0f; // Intake pipe (shorter, narrower) - double intLength = 1; - double intRadius = 0.01; + double intLength = 0.1; + double intRadius = 1 * Units.cm; 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); // Cylinder (starts at BDC, fresh charge) 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); engineCyl.ignition = true; @@ -107,7 +107,9 @@ namespace FluidSim.Core 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; engineCyl.TargetPeakPressure = targetPressure; @@ -211,10 +213,10 @@ namespace FluidSim.Core float centerY = winH / 2f; const float T_ambient = 293.15f; - const float T_hot = 1500f; - const float T_cold = 0f; - const float R = 287.05f; - float deltaHot = T_hot - T_ambient; + const float T_hot = 1500f; + const float T_cold = 0f; + const float R = 287.05f; + float deltaHot = T_hot - T_ambient; float deltaCold = T_ambient - T_cold; float NormaliseTemperature(double T) @@ -240,7 +242,7 @@ namespace FluidSim.Core target.Draw(cylRect); // ---- Piston ---- - float pistonWidth = cylW - 12f; + float pistonWidth = cylW - 12f; float pistonHeight = 16f; float pistonFraction = (float)engineCyl.PistonPositionFraction; float pistonTopY = cylRect.Position.Y + pistonFraction * (cylH - pistonHeight); @@ -251,12 +253,36 @@ namespace FluidSim.Core }; 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) ---- - 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); // ---- 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); } @@ -276,11 +302,11 @@ namespace FluidSim.Core for (int i = 0; i < n; i++) { float x = startX + i * dx; - double p = pipe.GetCellPressure(i); + double p = pipe.GetCellPressure(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; float tn = normaliseTemp(T); @@ -289,7 +315,7 @@ namespace FluidSim.Core byte gC = (byte)(255 * (1 - Math.Abs(tn))); var col = new Color(rC, gC, bC); - vertices[i * 2] = new Vertex(new Vector2f(x, centerY - r), col); + vertices[i * 2] = new Vertex(new Vector2f(x, centerY - r), col); vertices[i * 2 + 1] = new Vertex(new Vector2f(x, centerY + r), col); }