added valves display
This commit is contained in:
@@ -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
46
Components/Nozzleflow.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FluidSim.Components
|
||||||
|
{
|
||||||
|
public static class NozzleFlow
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the nozzle‑exit 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 high‑pressure side
|
||||||
|
mdot = rhoExit * uExit * area;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ambient cell for non‑reflecting 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user