Example #1
0
        // Be sure to set th7, eta_n, p8
        // Sets Anozzle and V8
        private void CalculateANozzle()
        {
            double exitEnergy = th7.Cp * th7.T * eta_n * (1.0 - Math.Pow(p8 / th7.P, th7.R / th7.Cp));

            V8  = Math.Sqrt(Math.Abs(2d * exitEnergy));
            V8 *= Math.Sign(exitEnergy);
            double exitMach = th7.CalculateMach(Math.Abs(V8));

            Anozzle = th7.CalculateFlowArea(mdot, exitMach);
        }
Example #2
0
        protected void InitializeEngine()
        {
            //calculate TTR at design point first

            // Don't overwrite th0 and th1
            EngineThermodynamics ambientTherm = EngineThermodynamics.StandardConditions(false);

            ambientTherm.T = T_d;
            EngineThermodynamics inletTherm = ambientTherm.ChangeReferenceFrameMach(M_d);

            th7    = inletTherm.AddFuelToTemperature(9999d, h_f, throttle: throttle, maxFar: maxFar);
            th7.P *= 0.95;

            double massFlow = inletTherm.CalculateMassFlow(Aref, 0.5d);

            Athroat = th7.CalculateFlowArea(massFlow * th7.MassRatio, 1d);

            if (!adjustableNozzle)
            {
                p8 = ambientTherm.P;
                CalculateANozzle();
            }
        }
Example #3
0
        public void FitEngine(double dryThrust, double drySFC, double wetThrust, double idleNozzlePressureRatio, double defaultTPR = 1d)
        {
            float TPR = AJEInlet.OverallStaticTPR((float)defaultTPR);

            SetEngineState(true, 1d);
            SetStaticConditions(usePlanetarium: false, overallTPR: TPR);

            double dryThrottle = Afterburning ? 2d / 3d : 1d;

            this.drySFC = drySFC;
            if (drySFC > 0d)
            {
                CalculatePerformance(1d, dryThrottle, 1d, 1d);
                if (Math.Abs(SFC / drySFC - 1d) > 0.0001d)
                {
                    h_f = SolverMathUtil.BrentsMethod(DrySFCFittingFunction, 10e6, 200e6, maxIter: 1000);
                    CalculateTTR();
                }
            }

            // Min throttle
            // Set to make sure tailpipe pressure is greater than ambient

            minThrottle = 0.01f;
            CalculatePerformance(1d, 0f, 1d, 1d);

            idleNPR = idleNozzlePressureRatio;
            if (th7.P > 1.25 * th0.P)
            {
                minThrottle = 0.01f;
            }
            else
            {
                CalculatePerformance(1d, dryThrottle, 1d, 1d);
                if (th7.P < idleNPR * th0.P)
                {
                    Debug.Log("Cannot fit min throttle because jet pipe pressure is too low.  Perhaps TIT is too low or CPR is too high.");
                    minThrottle = 0.01f;
                }
                else
                {
                    minThrottle = SolverMathUtil.BrentsMethod(MinThrottleFittingFunction, 0.01f, 1f, maxIter: 1000);
                }
            }

            CalculatePerformance(1d, dryThrottle, 1d, 1d);
            double aTurbine = th4.CalculateFlowArea(coreAirflow * th4.MassRatio, 1d);
            double fakeAref = th1.CalculateFlowArea(coreAirflow, 0.5d);

            turbineAreaRatio = aTurbine / fakeAref;

            this.dryThrust = dryThrust;
            if (dryThrust > 0d)
            {
                CalculatePerformance(1d, dryThrottle, 1d, 1d);

                Aref *= dryThrust / thrust;
            }
            this.wetThrust = wetThrust;
            if (wetThrust > 0d)
            {
                bool   doFit  = true;
                double oldTt7 = Tt7;

                if (Tt7 <= 0d)
                {
                    Tt7 = 2500d;
                }
                else
                {
                    CalculatePerformance(1d, 1d, 1d, 1d);
                    if (Math.Abs(thrust / wetThrust - 1d) <= 0.0001d)
                    {
                        // TAB already correct, no need to fit
                        doFit = false;
                    }
                }

                // Check bounds
                if (doFit)
                {
                    CalculatePerformance(1d, 2d / 3d, 1d, 1d);

                    if (thrust >= wetThrust)
                    {
                        Debug.LogWarning("Cannot fit wet thrust on engine because dry thrust is already greater than specified value.");
                        doFit = false;
                    }

                    Tt7 = 4000d;
                    CalculatePerformance(1d, 1d, 1d, 1d);
                    if (thrust <= wetThrust)
                    {
                        Debug.LogWarning("Cannot fit wet thrust on engine solver because it would require an afterburner temperature of more than 4000 K.");
                        doFit = false;
                    }
                }

                if (doFit)
                {
                    Tt7 = SolverMathUtil.BrentsMethod(WetThrustFittingFunction, th5.T, 4000d, maxIter: 1000);
                }
                else
                {
                    Tt7 = oldTt7;
                }
            }
        }
Example #4
0
        public override void CalculatePerformance(double airRatio, double commandedThrottle, double flowMult, double ispMult)
        {
            // set base bits
            base.CalculatePerformance(airRatio, commandedThrottle, flowMult, ispMult);

            // if we're not combusting, don't combust and start cooling off
            combusting   = running;
            statusString = "Nominal";
            if (running && (!oxygen || eair0 <= 0d))
            {
                combusting   = false;
                statusString = "No oxygen";
            }
            else if (ffFraction <= 0d)
            {
                combusting   = false;
                statusString = "No fuel";
            }
            else if (airRatio < 0.01d)
            {
                combusting   = false;
                statusString = "Insufficient intake area";
            }
            else if (underwater)
            {
                combusting   = false;
                statusString = "Nozzle in water";
            }

            if (combusting)
            {
                if (Tt7 > 0)
                {
                    if (unifiedThrottle)
                    {
                        mainThrottle = commandedThrottle;
                        abThrottle   = commandedThrottle;
                    }
                    else
                    {
                        mainThrottle = Math.Min(commandedThrottle * 1.5d, 1d);
                        abThrottle   = Math.Max(commandedThrottle * 3d - 2d, 0d);
                    }
                }
                else
                {
                    mainThrottle = commandedThrottle;
                    abThrottle   = 0d;
                }

                double coreThrottle = SolverMathUtil.Lerp(minThrottle, 1d, mainThrottle);

                prat3 = CPR;
                double invfac      = eta_c * th1.Gamma / (th1.Gamma - 1.0);
                double turbineWork = 0d;
                for (int i = 0; i < 20; i++)    //use iteration to calculate CPR
                {
                    th3 = th1.AdiabaticProcessWithPressureRatio(prat3, efficiency: eta_c);
                    // FIXME use ffFraction here? Instead of just multiplying thrust by fuel fraction in the module?
                    // is so, set multiplyThrustByFuelFrac = false in the ModuleEnginesAJEJet.
                    th4 = th3.AddFuelToTemperature(Tt4, h_f, throttle: coreThrottle);
                    th5 = th4.AdiabaticProcessWithTempRatio(TTR, out turbineWork, eta_t);

                    th3 = th1.AdiabaticProcessWithWork(turbineWork / (1d + fanWorkConstant), efficiency: eta_c);

                    double x = prat3;

                    prat3 = th3.P / th1.P;

                    if (Math.Abs(x - prat3) < 0.01)
                    {
                        break;
                    }
                }

                if (BPR > 0d)
                {
                    th2           = th1.AdiabaticProcessWithWork(turbineWork * fanWorkConstant / (1d + fanWorkConstant) / BPR, efficiency: eta_c);
                    th2.MassRatio = BPR;
                    prat2         = th2.P / th1.P;
                }

                if (exhaustMixer && BPR > 0)//exhaust mixer
                {
                    th2.P *= 0.98;
                    th6    = EngineThermodynamics.MixStreams(th5, th2);
                }
                else
                {
                    th6 = th5;
                }

                if (Tt7 > 0)
                {
                    th7 = th6.AddFuelToTemperature(Tt7, h_f, throttle: abThrottle);
                }
                else
                {
                    th7 = th6;
                }

                //Nozzle code is from NASA

                double p8, V8;
                //double A8;
                double epr = th7.P / th1.P;
                double etr = th7.T / th1.T;

                // The factor of 0.75 implies that the mach number of air entering the compressor is about 0.5
                // The factor can be calculated as
                // 1 / (1 - ff_ab) * sqrt(gamma_c/gamma_ab * R_ab / R_c) * M * (1 + (gamma_c + 1)/2 * M^2)^(-(gamma_c + 1)/(2 * (gamma_c - 1)) / ((gamma_ab + 1) / 2)^(-(gamma_ab + 1)/(2 * (gamma_ab - 1))
                //
                //A8 = .75 * Aref * th7.MassRatio * Math.Sqrt(th1.Gamma / th7.Gamma * th7.R / th1.R) * Math.Sqrt(etr) / epr;//ratio of nozzle area to ref area
                //double area8max = .75 * Math.Sqrt(etr) / epr;//ratio of nozzle area to ref area
                //A8 = area8max * Aref;
                //if (exhaustMixer && BPR > 0)
                //    A8 *= (1 + BPR);
                //double eair = th7.P * Math.Sqrt(th7.Gamma / th7.R / th7.T) *
                //    Math.Pow((0.5d + 0.5d * th7.Gamma), 0.5d * (1d + th7.Gamma) / (1d - th7.Gamma));//corrected mass flow per area
                //mdot = eair * A8;

                // Assume turbine is choked all the time
                coreAirflow = th4.CalculateMassFlow(Aref * turbineAreaRatio, 1d) / th4.MassRatio;
                mdot        = th7.MassRatio * coreAirflow;

                if (!adjustableNozzle)
                {
                    p8 = th7.ChokedPressure();
                    if (p8 < th0.P)
                    {
                        p8 = th0.P;
                    }
                }
                else
                {
                    p8 = th0.P;
                }
                double exitEnergy = th7.Cp * th7.T * eta_n * (1.0 - Math.Pow(p8 / th7.P, th7.R / th7.Cp));
                V8  = Math.Sqrt(Math.Abs(2d * exitEnergy));    //exit velocity - may be negative under certain conditions
                V8 *= Math.Sign(exitEnergy);
                double exitMach = th7.CalculateMach(Math.Abs(V8));
                Anozzle = th7.CalculateFlowArea(mdot, exitMach);
                thrust  = V8 * mdot + (p8 - th0.P) * Anozzle;
                thrust -= mdot * (1d - th7.FF) * (vel);//ram drag

                if (BPR > 0d && FPR > 1d && exhaustMixer == false)
                {
                    //fan thrust from NASA
                    double pfexit = th2.ChokedPressure();
                    if (pfexit < th0.P)
                    {
                        pfexit = th0.P;
                    }
                    double fExitEnergy = th2.Cp * th2.T * eta_n * (1d - Math.Pow(pfexit / th2.P, th2.R / th2.Cp));
                    double ues         = Math.Sqrt(Math.Abs(2d * fExitEnergy));
                    ues *= Math.Sign(fExitEnergy);
                    double bypassAirFlow = coreAirflow * th2.MassRatio; // th2.MassRatio will be equal to BPR at this point
                    double ANozzleBypass = th2.CalculateFlowArea(bypassAirFlow, th2.CalculateMach(ues));
                    thrust += bypassAirFlow * ues + (pfexit - p0) * ANozzleBypass;
                    thrust -= bypassAirFlow * vel;
                }

                thrust  *= flowMult * ispMult;
                fuelFlow = mdot * th7.FF * flowMult;
                Isp      = thrust / (fuelFlow * 9.80665);
                SFC      = 3600d / Isp;

                /*
                 * debugstring = "";
                 * debugstring += "TTR:\t" + TTR.ToString("F3") + "\r\n";
                 * debugstring += "CPR:\t" + prat3.ToString("F3") + "\r\n"; ;
                 * debugstring += "p0: " + th0.P.ToString("F2") + "\tt0: " + th0.T.ToString("F2") + "\r\n";
                 * debugstring += "P1: " + th1.P.ToString("F2") + "\tT1: " + th1.T.ToString("F2") + "\r\n";
                 * debugstring += "P2: " + th2.P.ToString("F2") + "\tT2: " + th2.T.ToString("F2") + "\r\n";
                 * debugstring += "P3: " + th3.P.ToString("F2") + "\tT3: " + th3.T.ToString("F2") + "\r\n";
                 * debugstring += "P4: " + th4.P.ToString("F2") + "\tT4: " + th4.T.ToString("F2") + "\r\n";
                 * debugstring += "P5: " + th5.P.ToString("F2") + "\tT5: " + th5.T.ToString("F2") + "\r\n";
                 * debugstring += "P6: " + th6.P.ToString("F2") + "\tT6: " + th6.T.ToString("F2") + "\r\n";
                 * debugstring += "P7: " + th7.P.ToString("F2") + "\tT7: " + th7.ToString("F2") + "\r\n";
                 * debugstring += "EPR: " + epr.ToString("F2") + "\tETR: " + etr.ToString("F2") + "\r\n";
                 *
                 * debugstring += "FF: " + th5.FF.ToString("P") + "\t";
                 * debugstring += "FF_AB: " + th7.FF.ToString("P") + "\r\n";
                 * debugstring += "V8: " + V8.ToString("F2") + "\tA8: " + A8.ToString("F2") + "\r\n";
                 * debugstring += "Thrust: " + (thrust / 1000).ToString("F1") + "\tmdot: " + mdot.ToString("F2") + "\r\n";
                 * debugstring += "Isp: " + Isp.ToString("F0") + "\tSFC: " + (3600 / Isp).ToString("F3") + "\r\n";
                 * Debug.Log(debugstring);*/
            }
            else
            {
                double shutdownScalar = Math.Pow(spoolFactor, TimeWarp.fixedDeltaTime);

                th3.T = Math.Max(t0, th3.T * shutdownScalar - 4d);

                mainThrottle = Math.Max(0d, mainThrottle * shutdownScalar - 0.05d);
                if (Tt7 > 0)
                {
                    abThrottle = Math.Max(0d, abThrottle * shutdownScalar - 0.05d);
                }
            }
            // Set FX power
            if (Tt7 == 0)
            {
                fxPower = (float)mainThrottle;
            }
            else
            {
                fxPower = (float)(mainThrottle * 0.25d + abThrottle * 0.75d);
            }
        }
Example #5
0
        public override void CalculatePerformance(double airRatio, double commandedThrottle, double flowMult, double ispMult)
        {
            // set base bits
            base.CalculatePerformance(airRatio, commandedThrottle, flowMult, ispMult);

            // if we're not combusting, don't combust and start cooling off
            combusting   = running;
            statusString = "Nominal";
            if (running && (!oxygen || eair0 <= 0d))
            {
                combusting   = false;
                statusString = "No oxygen";
            }
            else if (ffFraction <= 0d)
            {
                combusting   = false;
                statusString = "No fuel";
            }
            else if (th1.P * 0.9 < th0.P)
            {
                combusting   = false;
                statusString = "Below ignition speed";
            }
            else if (airRatio < 0.01d)
            {
                combusting   = false;
                statusString = "Insufficient intake area";
            }
            else if (underwater)
            {
                combusting   = false;
                statusString = "Nozzle in water";
            }

            if (combusting)
            {
                th7    = th1.AddFuelToTemperature(9999d, h_f, throttle: throttle, maxFar: maxFar);
                th7.P *= 0.95;

                //Nozzle code is from NASA

                //double A8;
                double epr = th7.P / th1.P;
                double etr = th7.T / th1.T;

                coreAirflow = th7.CalculateMassFlow(Athroat, 1d) / th7.MassRatio;
                mdot        = th7.MassRatio * coreAirflow;

                if (adjustableNozzle)
                {
                    p8 = th0.P;
                    double exitEnergy = th7.Cp * th7.T * eta_n * (1.0 - Math.Pow(p8 / th7.P, th7.R / th7.Cp));
                    V8  = Math.Sqrt(Math.Abs(2d * exitEnergy));    //exit velocity - may be negative under certain conditions
                    V8 *= Math.Sign(exitEnergy);
                    double exitMach = th7.CalculateMach(Math.Abs(V8));
                    Anozzle = th7.CalculateFlowArea(mdot, exitMach);
                }

                thrust  = V8 * mdot + (p8 - th0.P) * Anozzle;
                thrust -= mdot * (1d - th7.FF) * (vel);//ram drag

                thrust  *= flowMult * ispMult;
                fuelFlow = mdot * th7.FF * flowMult;
                Isp      = thrust / (fuelFlow * 9.80665);
                SFC      = 3600d / Isp;
            }
            // Set FX power
            fxPower = (float)throttle;
        }