using System; using FluidSim.Components; namespace FluidSim.Core { public static class NozzleFlow { public static void Compute(Volume0D vol, double area, double downstreamPressure, out double massFlow, out double rhoFace, out double uFace, out double pFace, double gamma = 1.4) { massFlow = 0.0; rhoFace = 0.0; uFace = 0.0; pFace = 0.0; if (vol == null || vol.Mass <= 0 || vol.Volume <= 0) return; double p0 = vol.Pressure; double T0 = vol.Temperature; double R = vol.GasConstant; double rho0 = vol.Density; if (double.IsNaN(p0) || double.IsNaN(T0) || double.IsNaN(rho0) || p0 <= 0 || T0 <= 0 || rho0 <= 0) return; double pr = downstreamPressure / p0; double choked = Math.Pow(2.0 / (gamma + 1.0), gamma / (gamma - 1.0)); // If pr > 1, flow is INTO the cylinder (reverse), so we swap the roles. bool reverse = (pr > 1.0); if (reverse) { // Treat the cylinder as the downstream, the pipe as the upstream. double p_up = downstreamPressure; double T_up = 300.0; // pipe temperature (ambient) double rho_up = downstreamPressure / (R * T_up); double pr_rev = p0 / p_up; // now cylinder / pipe if (pr_rev < choked) pr_rev = choked; double M = Math.Sqrt((2.0 / (gamma - 1.0)) * (Math.Pow(pr_rev, -(gamma - 1.0) / gamma) - 1.0)); if (double.IsNaN(M)) return; // Flow from pipe INTO cylinder (positive mass flow into volume) uFace = M * Math.Sqrt(gamma * R * T_up); rhoFace = rho_up * Math.Pow(pr_rev, 1.0 / gamma); pFace = p_up * pr_rev; massFlow = rhoFace * uFace * area; // massFlow is positive = into cylinder } else { // Normal flow out of cylinder if (pr < choked) pr = choked; double M = Math.Sqrt((2.0 / (gamma - 1.0)) * (Math.Pow(pr, -(gamma - 1.0) / gamma) - 1.0)); if (double.IsNaN(M)) return; uFace = M * Math.Sqrt(gamma * R * T0); rhoFace = rho0 * Math.Pow(pr, 1.0 / gamma); pFace = p0 * pr; massFlow = -rhoFace * uFace * area; // negative = out of cylinder } if (double.IsNaN(massFlow) || double.IsInfinity(massFlow)) massFlow = 0.0; } } }