Files
FluidSim/Core/OpenEndLink.cs

123 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using FluidSim.Components;
namespace FluidSim.Core
{
/// <summary>
/// Characteristic openend 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;
// Last resolved state (for audio / monitoring)
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;
}
/// <summary>
/// Compute the ghost state and mass flow for one substep.
/// </summary>
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 rhoGhost, uGhost, pGhost;
double mdot;
if (IsLeftEnd)
{
// Left end: outgoing invariant is J- = u - 2c/(γ-1)
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;
if (uInt >= cInt) // supersonic outflow
{
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;
pGhost = pAmb;
}
else // subsonic inflow (uInt < 0)
{
double rhoAmb = pAmb / (287.0 * 300.0);
double cAmb = Math.Sqrt(gamma * pAmb / rhoAmb);
uGhost = J_plus - 2.0 * cAmb / gm1;
rhoGhost = rhoAmb;
pGhost = pAmb;
}
}
// 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
LastMassFlowRate = mdot;
LastFaceDensity = rhoGhost;
LastFaceVelocity = uGhost;
LastFacePressure = pGhost;
}
}
}