using System;

namespace FluidSim.Core
{
    public static class IsentropicOrifice
    {
        public static void Compute(
            float pUp, float rhoUp, float TUp,
            float pDown, float gamma, float R, float area, float Cd,
            out float mdot, out float rhoFace, out float uFace, out float pFace)
        {
            mdot = 0f; rhoFace = rhoUp; uFace = 0f; pFace = pUp;
            if (area <= 0f || pUp <= 0f || rhoUp <= 0f || TUp <= 0f) return;

            float pr = MathF.Min(pDown / pUp, 1f);
            if (pr < 1e-6f) pr = 1e-6f;
            float prCrit = MathF.Pow(2f / (gamma + 1f), gamma / (gamma - 1f));
            if (pr < prCrit) pr = prCrit;

            float exponent = (gamma - 1f) / gamma;
            float M = MathF.Sqrt((2f / (gamma - 1f)) * (MathF.Pow(pr, -exponent) - 1f));
            if (float.IsNaN(M)) M = 0f;

            float aUp = MathF.Sqrt(gamma * R * TUp);
            uFace = M * aUp;
            rhoFace = rhoUp * MathF.Pow(pr, 1f / gamma);
            pFace = pUp * pr;
            mdot = rhoFace * uFace * area * Cd;
        }
    }
}