Engine working

This commit is contained in:
max
2026-05-07 21:48:37 +02:00
parent 92d84eacfe
commit b3230844b7
14 changed files with 441 additions and 486 deletions

View File

@@ -7,10 +7,10 @@ namespace FluidSim.Components
/// <summary>
/// 1D compressible Euler pipe with LaxFriedrichs finitevolume scheme.
/// Ghost states are set externally via SetGhostLeft/Right; they are always required.
/// Now includes a passive scalar for air mass fraction.
/// </summary>
public class Pipe1D : IComponent
{
// ---------- Compiletime profiling flag ----------
public const bool EnableDetailedProfiling = false; // set to false in release builds
public Port PortA { get; }
@@ -36,10 +36,11 @@ namespace FluidSim.Components
private readonly double _gamma = 1.4;
private double[] _rho, _rhou, _E;
private double[] _fluxM, _fluxP, _fluxE; // flux at cell faces (0.._n) kept for possible external use, not used internally anymore
private double[] _Y; // air mass fraction
private double[] _fluxM, _fluxP, _fluxE;
private double _rhoGhostL, _uGhostL, _pGhostL;
private double _rhoGhostR, _uGhostR, _pGhostR;
private double _rhoGhostL, _uGhostL, _pGhostL, _YGhostL;
private double _rhoGhostR, _uGhostR, _pGhostR, _YGhostR;
private bool _ghostLValid, _ghostRValid;
private double _laminarCoeff;
@@ -65,7 +66,7 @@ namespace FluidSim.Components
_rho = new double[_n];
_rhou = new double[_n];
_E = new double[_n];
_Y = new double[_n];
_fluxM = new double[_n + 1];
_fluxP = new double[_n + 1];
_fluxE = new double[_n + 1];
@@ -87,16 +88,19 @@ namespace FluidSim.Components
public void UpdateState(double dt) { }
// ---------- Ghost interface ----------
public void SetGhostLeft(double rho, double u, double p)
public void SetGhostLeft(double rho, double u, double p, double airFraction)
{
_rhoGhostL = rho; _uGhostL = u; _pGhostL = p; _ghostLValid = true;
_rhoGhostL = rho; _uGhostL = u; _pGhostL = p; _YGhostL = airFraction; _ghostLValid = true;
}
public void SetGhostRight(double rho, double u, double p)
public void SetGhostRight(double rho, double u, double p, double airFraction)
{
_rhoGhostR = rho; _uGhostR = u; _pGhostR = p; _ghostRValid = true;
_rhoGhostR = rho; _uGhostR = u; _pGhostR = p; _YGhostR = airFraction; _ghostRValid = true;
}
public void ClearGhostFlags() { _ghostLValid = false; _ghostRValid = false; }
public double GetInteriorAirFractionLeft() => _Y[0];
public double GetInteriorAirFractionRight() => _Y[_n - 1];
public (double rho, double u, double p) GetInteriorStateLeft()
{
double rho = Math.Max(_rho[0], 1e-12);
@@ -172,6 +176,34 @@ namespace FluidSim.Components
t0 = t1;
}
// ---------- Local flux functions ----------
void LaxFlux(double rL, double uL, double pL, double cL,
double rR, double uR, double pR, double cR,
out double fm, out double fp, out double fe)
{
double EL = pL / (gm1 * rL) + 0.5 * uL * uL;
double ER = pR / (gm1 * rR) + 0.5 * uR * uR;
double Fm_L = rL * uL;
double Fp_L = rL * uL * uL + pL;
double Fe_L = (rL * EL + pL) * uL;
double Fm_R = rR * uR;
double Fp_R = rR * uR * uR + pR;
double Fe_R = (rR * ER + pR) * uR;
double alpha = Math.Max(Math.Abs(uL) + cL, Math.Abs(uR) + cR);
fm = 0.5 * (Fm_L + Fm_R) - 0.5 * alpha * (rR - rL);
fp = 0.5 * (Fp_L + Fp_R) - 0.5 * alpha * (rR * uR - rL * uL);
fe = 0.5 * (Fe_L + Fe_R) - 0.5 * alpha * (rR * ER - rL * EL);
}
void ScalarFlux(double rL, double uL, double cL, double YL,
double rR, double uR, double cR, double YR,
double alpha, out double fy)
{
double Fm_L = rL * uL;
double Fm_R = rR * uR;
fy = 0.5 * (Fm_L * YL + Fm_R * YR) - 0.5 * alpha * (rR * YR - rL * YL);
}
// ---------- Phase 2: Left face flux (ghostL cell 0) ----------
double rL_ghost = Math.Max(_rhoGhostL, 1e-12);
double pL_ghost = _pGhostL;
@@ -182,6 +214,12 @@ namespace FluidSim.Components
_rho[0], _rhou[0] / Math.Max(_rho[0], 1e-12), p[0], c[0],
out double fluxM_left, out double fluxP_left, out double fluxE_left);
double alphaLeft = Math.Max(Math.Abs(uL_ghost) + cL_ghost,
Math.Abs(_rhou[0] / Math.Max(_rho[0], 1e-12)) + c[0]);
ScalarFlux(rL_ghost, uL_ghost, cL_ghost, _YGhostL,
_rho[0], _rhou[0] / Math.Max(_rho[0], 1e-12), c[0], _Y[0],
alphaLeft, out double fluxY_left);
if (EnableDetailedProfiling)
{
t1 = Stopwatch.GetTimestamp();
@@ -193,6 +231,7 @@ namespace FluidSim.Components
double fluxM_prev = fluxM_left;
double fluxP_prev = fluxP_left;
double fluxE_prev = fluxE_left;
double fluxY_prev = fluxY_left;
for (int i = 0; i < n - 1; i++)
{
@@ -203,23 +242,31 @@ namespace FluidSim.Components
double uL = _rhou[iL] / rL;
double pL = p[iL];
double cL = c[iL];
double YL = _Y[iL];
double rR = Math.Max(_rho[iR], 1e-12);
double uR = _rhou[iR] / rR;
double pR = p[iR];
double cR = c[iR];
double YR = _Y[iR];
LaxFlux(rL, uL, pL, cL, rR, uR, pR, cR,
out double fluxM_right, out double fluxP_right, out double fluxE_right);
double alpha = Math.Max(Math.Abs(uL) + cL, Math.Abs(uR) + cR);
ScalarFlux(rL, uL, cL, YL, rR, uR, cR, YR, alpha, out double fluxY_right);
// Update cell i
double r = _rho[i];
double ru = _rhou[i];
double E = _E[i];
double Y = _Y[i];
double newR = r - dt_dx * (fluxM_right - fluxM_prev);
double newRu = ru - dt_dx * (fluxP_right - fluxP_prev);
double newE = E - dt_dx * (fluxE_right - fluxE_prev);
double oldRhoY = r * Y;
double newRhoY = oldRhoY - dt_dx * (fluxY_right - fluxY_prev);
double dampingFactor = Math.Exp(-coeff / Math.Max(r, 1e-12) * dt);
newRu *= dampingFactor;
@@ -234,10 +281,12 @@ namespace FluidSim.Components
_rho[i] = newR;
_rhou[i] = newRu;
_E[i] = newE;
_Y[i] = Math.Clamp(newRhoY / newR, 0.0, 1.0);
fluxM_prev = fluxM_right;
fluxP_prev = fluxP_right;
fluxE_prev = fluxE_right;
fluxY_prev = fluxY_right;
}
if (EnableDetailedProfiling)
@@ -253,20 +302,31 @@ namespace FluidSim.Components
double uR_ghost = _uGhostR;
double cR_ghost = Math.Sqrt(gamma * pR_ghost / rR_ghost);
LaxFlux(_rho[n - 1], _rhou[n - 1] / Math.Max(_rho[n - 1], 1e-12), p[n - 1], c[n - 1],
double rInt = _rho[n - 1];
double uInt = _rhou[n - 1] / Math.Max(rInt, 1e-12);
LaxFlux(rInt, uInt, p[n - 1], c[n - 1],
rR_ghost, uR_ghost, pR_ghost, cR_ghost,
out double fluxM_right_final, out double fluxP_right_final, out double fluxE_right_final);
// Update last cell (identical to interior, but with final fluxes)
double alphaRight = Math.Max(Math.Abs(uInt) + c[n - 1], Math.Abs(uR_ghost) + cR_ghost);
ScalarFlux(rInt, uInt, c[n - 1], _Y[n - 1],
rR_ghost, uR_ghost, cR_ghost, _YGhostR,
alphaRight, out double fluxY_right_final);
// Update last cell
{
int i = n - 1;
double r = _rho[i];
double ru = _rhou[i];
double E = _E[i];
double Y = _Y[i];
double newR = r - dt_dx * (fluxM_right_final - fluxM_prev);
double newRu = ru - dt_dx * (fluxP_right_final - fluxP_prev);
double newE = E - dt_dx * (fluxE_right_final - fluxE_prev);
double oldRhoY = r * Y;
double newRhoY = oldRhoY - dt_dx * (fluxY_right_final - fluxY_prev);
double dampingFactor = Math.Exp(-coeff / Math.Max(r, 1e-12) * dt);
newRu *= dampingFactor;
@@ -281,6 +341,7 @@ namespace FluidSim.Components
_rho[i] = newR;
_rhou[i] = newRu;
_E[i] = newE;
_Y[i] = Math.Clamp(newRhoY / newR, 0.0, 1.0);
}
if (EnableDetailedProfiling)
@@ -295,11 +356,13 @@ namespace FluidSim.Components
PortA.Pressure = pA; PortA.Density = rhoA;
PortA.Temperature = pA / (rhoA * 287.0);
PortA.SpecificEnthalpy = gm1 / (gamma - 1.0) * pA / rhoA;
PortA.AirFraction = _Y[0];
(double rhoB, double uB, double pB) = GetInteriorStateRight();
PortB.Pressure = pB; PortB.Density = rhoB;
PortB.Temperature = pB / (rhoB * 287.0);
PortB.SpecificEnthalpy = gm1 / (gamma - 1.0) * pB / rhoB;
PortB.AirFraction = _Y[_n - 1];
if (EnableDetailedProfiling)
{
@@ -308,48 +371,6 @@ namespace FluidSim.Components
}
}
// ---------- Local LaxFriedrichs flux function ----------
private void LaxFlux(double rL, double uL, double pL, double cL,
double rR, double uR, double pR, double cR,
out double fm, out double fp, out double fe)
{
double gm1 = _gamma - 1.0;
double EL = pL / (gm1 * rL) + 0.5 * uL * uL;
double ER = pR / (gm1 * rR) + 0.5 * uR * uR;
double Fm_L = rL * uL;
double Fp_L = rL * uL * uL + pL;
double Fe_L = (rL * EL + pL) * uL;
double Fm_R = rR * uR;
double Fp_R = rR * uR * uR + pR;
double Fe_R = (rR * ER + pR) * uR;
double alpha = Math.Max(Math.Abs(uL) + cL, Math.Abs(uR) + cR);
fm = 0.5 * (Fm_L + Fm_R) - 0.5 * alpha * (rR - rL);
fp = 0.5 * (Fp_L + Fp_R) - 0.5 * alpha * (rR * uR - rL * uL);
fe = 0.5 * (Fe_L + Fe_R) - 0.5 * alpha * (rR * ER - rL * EL);
}
// Original LaxFriedrichsFlux (kept for compatibility, can be removed if unused)
private void LaxFriedrichsFlux(double rL, double uL, double pL, double eL,
double rR, double uR, double pR, double eR,
out double fm, out double fp, out double fe)
{
double rhoL = rL, rhoR = rR;
double EL = rhoL * eL;
double ER = rhoR * eR;
double Fm_L = rhoL * uL;
double Fp_L = rhoL * uL * uL + pL;
double Fe_L = (EL + pL) * uL;
double Fm_R = rhoR * uR;
double Fp_R = rhoR * uR * uR + pR;
double Fe_R = (ER + pR) * uR;
double cL = Math.Sqrt(_gamma * pL / rL);
double cR = Math.Sqrt(_gamma * pR / rR);
double alpha = Math.Max(Math.Abs(uL) + cL, Math.Abs(uR) + cR);
fm = 0.5 * (Fm_L + Fm_R) - 0.5 * alpha * (rhoR - rhoL);
fp = 0.5 * (Fp_L + Fp_R) - 0.5 * alpha * (rhoR * uR - rhoL * uL);
fe = 0.5 * (Fe_L + Fe_R) - 0.5 * alpha * (ER - EL);
}
private double PressureScalar(int i)
{
double rho = Math.Max(_rho[i], 1e-12);
@@ -365,6 +386,7 @@ namespace FluidSim.Components
_rho[i] = rho;
_rhou[i] = rho * u;
_E[i] = E;
_Y[i] = 1.0; // initially pure air
}
}
@@ -376,6 +398,7 @@ namespace FluidSim.Components
_rho[i] = rho;
_rhou[i] = rho * u;
_E[i] = E;
_Y[i] = 1.0;
}
public void SetCellPressure(int i, double p)