added valves display
This commit is contained in:
@@ -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;
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user