97 lines
3.4 KiB
C#
97 lines
3.4 KiB
C#
using System;
|
|
using FluidSim.Components;
|
|
|
|
namespace FluidSim.Core
|
|
{
|
|
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;
|
|
|
|
public double LastMassFlowRate { get; private set; }
|
|
public double LastFaceDensity { get; private set; }
|
|
public double LastFaceVelocity { get; private set; }
|
|
public double LastFacePressure { get; private set; }
|
|
|
|
public OpenEndLink(Pipe1D pipe, bool isLeftEnd)
|
|
{
|
|
Pipe = pipe ?? throw new ArgumentNullException(nameof(pipe));
|
|
IsLeftEnd = isLeftEnd;
|
|
}
|
|
|
|
public void Resolve(double dtSub)
|
|
{
|
|
(double rhoInt, double uInt, double pInt) = IsLeftEnd
|
|
? Pipe.GetInteriorStateLeft()
|
|
: Pipe.GetInteriorStateRight();
|
|
|
|
double gamma = Gamma;
|
|
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;
|
|
|
|
// ----- Supersonic outflow: extrapolate interior -----
|
|
bool supersonicOut = IsLeftEnd ? (uInt <= -cInt) : (uInt >= cInt);
|
|
if (supersonicOut)
|
|
{
|
|
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;
|
|
|
|
// 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);
|
|
|
|
bool outflowPossible = IsLeftEnd ? (uOut <= 0) : (uOut >= 0);
|
|
|
|
if (outflowPossible)
|
|
{
|
|
// Subsonic outflow
|
|
pGhost = pAmb;
|
|
rhoGhost = rhoOut;
|
|
uGhost = uOut;
|
|
}
|
|
else
|
|
{
|
|
// Subsonic inflow (ambient reservoir model)
|
|
pGhost = pAmb;
|
|
rhoGhost = rhoAmb;
|
|
uGhost = IsLeftEnd
|
|
? (J_minus + 2.0 * aAmb / gm1)
|
|
: (J_plus - 2.0 * aAmb / gm1);
|
|
}
|
|
}
|
|
|
|
if (IsLeftEnd)
|
|
Pipe.SetGhostLeft(rhoGhost, uGhost, pGhost);
|
|
else
|
|
Pipe.SetGhostRight(rhoGhost, uGhost, pGhost);
|
|
|
|
double area = Pipe.Area;
|
|
double mdot = rhoGhost * uGhost * area;
|
|
if (IsLeftEnd) mdot = -mdot;
|
|
LastMassFlowRate = mdot;
|
|
LastFaceDensity = rhoGhost;
|
|
LastFaceVelocity = uGhost;
|
|
LastFacePressure = pGhost;
|
|
}
|
|
}
|
|
} |