Open end working
This commit is contained in:
@@ -3,19 +3,15 @@ using FluidSim.Components;
|
||||
|
||||
namespace FluidSim.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Characteristic open‑end boundary condition.
|
||||
/// For subsonic outflow the outgoing Riemann invariant is conserved,
|
||||
/// and the ghost pressure is set to the prescribed ambient value.
|
||||
/// </summary>
|
||||
public class OpenEndLink
|
||||
{
|
||||
public Pipe1D Pipe { get; }
|
||||
public bool IsLeftEnd { get; }
|
||||
public double AmbientPressure { get; set; } = 101325.0;
|
||||
public double Gamma { get; set; } = 1.4;
|
||||
public double GasConstant { get; set; } = 287.0;
|
||||
public double AmbientTemperature { get; set; } = 300.0;
|
||||
|
||||
// Last resolved state (for audio / monitoring)
|
||||
public double LastMassFlowRate { get; private set; }
|
||||
public double LastFaceDensity { get; private set; }
|
||||
public double LastFaceVelocity { get; private set; }
|
||||
@@ -27,9 +23,6 @@ namespace FluidSim.Core
|
||||
IsLeftEnd = isLeftEnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute the ghost state and mass flow for one sub‑step.
|
||||
/// </summary>
|
||||
public void Resolve(double dtSub)
|
||||
{
|
||||
(double rhoInt, double uInt, double pInt) = IsLeftEnd
|
||||
@@ -40,80 +33,61 @@ namespace FluidSim.Core
|
||||
double gm1 = gamma - 1.0;
|
||||
double cInt = Math.Sqrt(gamma * pInt / Math.Max(rhoInt, 1e-12));
|
||||
double pAmb = AmbientPressure;
|
||||
double rhoAmb = pAmb / (GasConstant * AmbientTemperature);
|
||||
double aAmb = Math.Sqrt(gamma * pAmb / rhoAmb);
|
||||
|
||||
double rhoGhost, uGhost, pGhost;
|
||||
double mdot;
|
||||
|
||||
if (IsLeftEnd)
|
||||
// ----- Supersonic outflow: extrapolate interior -----
|
||||
bool supersonicOut = IsLeftEnd ? (uInt <= -cInt) : (uInt >= cInt);
|
||||
if (supersonicOut)
|
||||
{
|
||||
// Left end: outgoing invariant is J- = u - 2c/(γ-1)
|
||||
rhoGhost = rhoInt;
|
||||
uGhost = uInt;
|
||||
pGhost = pInt;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Riemann invariants
|
||||
double J_plus = uInt + 2.0 * cInt / gm1;
|
||||
double J_minus = uInt - 2.0 * cInt / gm1;
|
||||
|
||||
if (uInt <= -cInt) // supersonic inflow (all info from outside)
|
||||
{
|
||||
// Simple reservoir model – use ambient density and temperature 300 K
|
||||
rhoGhost = pAmb / (287.0 * 300.0);
|
||||
uGhost = uInt; // keep interior velocity (should be supersonic inward)
|
||||
pGhost = pAmb;
|
||||
}
|
||||
else if (uInt < 0) // subsonic inflow
|
||||
{
|
||||
double rhoAmb = pAmb / (287.0 * 300.0);
|
||||
double cAmb = Math.Sqrt(gamma * pAmb / rhoAmb);
|
||||
uGhost = J_minus + 2.0 * cAmb / gm1;
|
||||
rhoGhost = rhoAmb;
|
||||
pGhost = pAmb;
|
||||
}
|
||||
else // subsonic outflow (uInt >= 0)
|
||||
{
|
||||
double s = pInt / Math.Pow(rhoInt, gamma);
|
||||
rhoGhost = Math.Pow(pAmb / s, 1.0 / gamma);
|
||||
double cGhost = Math.Sqrt(gamma * pAmb / rhoGhost);
|
||||
uGhost = J_minus + 2.0 * cGhost / gm1;
|
||||
if (uGhost < 0) uGhost = 0;
|
||||
pGhost = pAmb;
|
||||
}
|
||||
}
|
||||
else // Right end
|
||||
{
|
||||
// Right end: outgoing invariant is J+ = u + 2c/(γ-1)
|
||||
double J_plus = uInt + 2.0 * cInt / gm1;
|
||||
// Trial subsonic outflow ghost state
|
||||
double s = pInt / Math.Pow(rhoInt, gamma);
|
||||
double rhoOut = Math.Pow(pAmb / s, 1.0 / gamma);
|
||||
double cOut = Math.Sqrt(gamma * pAmb / rhoOut);
|
||||
double uOut = IsLeftEnd
|
||||
? (J_minus + 2.0 * cOut / gm1)
|
||||
: (J_plus - 2.0 * cOut / gm1);
|
||||
|
||||
if (uInt >= cInt) // supersonic outflow
|
||||
bool outflowPossible = IsLeftEnd ? (uOut <= 0) : (uOut >= 0);
|
||||
|
||||
if (outflowPossible)
|
||||
{
|
||||
rhoGhost = rhoInt;
|
||||
uGhost = uInt;
|
||||
pGhost = pInt;
|
||||
}
|
||||
else if (uInt >= 0) // subsonic outflow
|
||||
{
|
||||
double s = pInt / Math.Pow(rhoInt, gamma);
|
||||
rhoGhost = Math.Pow(pAmb / s, 1.0 / gamma);
|
||||
double cGhost = Math.Sqrt(gamma * pAmb / rhoGhost);
|
||||
uGhost = J_plus - 2.0 * cGhost / gm1;
|
||||
if (uGhost < 0) uGhost = 0;
|
||||
// Subsonic outflow
|
||||
pGhost = pAmb;
|
||||
rhoGhost = rhoOut;
|
||||
uGhost = uOut;
|
||||
}
|
||||
else // subsonic inflow (uInt < 0)
|
||||
else
|
||||
{
|
||||
double rhoAmb = pAmb / (287.0 * 300.0);
|
||||
double cAmb = Math.Sqrt(gamma * pAmb / rhoAmb);
|
||||
uGhost = J_plus - 2.0 * cAmb / gm1;
|
||||
// Subsonic inflow (ambient reservoir model)
|
||||
pGhost = pAmb;
|
||||
rhoGhost = rhoAmb;
|
||||
pGhost = pAmb;
|
||||
uGhost = IsLeftEnd
|
||||
? (J_minus + 2.0 * aAmb / gm1)
|
||||
: (J_plus - 2.0 * aAmb / gm1);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply ghost to pipe
|
||||
if (IsLeftEnd)
|
||||
Pipe.SetGhostLeft(rhoGhost, uGhost, pGhost);
|
||||
else
|
||||
Pipe.SetGhostRight(rhoGhost, uGhost, pGhost);
|
||||
|
||||
// Mass flow (positive = out of pipe)
|
||||
double area = Pipe.Area;
|
||||
mdot = rhoGhost * uGhost * area;
|
||||
if (IsLeftEnd) mdot = -mdot; // positive u into pipe, so out of pipe is negative u
|
||||
double mdot = rhoGhost * uGhost * area;
|
||||
if (IsLeftEnd) mdot = -mdot;
|
||||
LastMassFlowRate = mdot;
|
||||
LastFaceDensity = rhoGhost;
|
||||
LastFaceVelocity = uGhost;
|
||||
|
||||
Reference in New Issue
Block a user