//--------------------------------------------------------- //Initialization Functions /// <summary> /// Sets the freestream properties /// </summary> /// <param name="altitude">altitude in m</param> /// <param name="pressure">pressure in kPa</param> /// <param name="temperature">temperature in K</param> /// <param name="velocity">velocity in m/s</param> /// <param name="hasOxygen">does the atmosphere contain oxygen</param> /// <param name="isUnderwater">Is the engine's thrust transform underwater</param> virtual public void SetFreestreamAndInlet(EngineThermodynamics ambientTherm, EngineThermodynamics inletTherm, double altitude, double inMach, Vector3 inVel, bool hasOxygen, bool isUnderwater) { th0.CopyFrom(ambientTherm); th1.CopyFrom(inletTherm); alt = altitude; p0 = ambientTherm.P; t0 = ambientTherm.T; rho = ambientTherm.Rho; oxygen = hasOxygen; underwater = isUnderwater; velocity = inVel; vel = velocity.magnitude; mach = inMach; Q = 0.5d * rho * vel * vel; P1 = inletTherm.P; T1 = inletTherm.T; Rho1 = inletTherm.Rho; gamma_c = inletTherm.Gamma; inv_gamma_c = 1d / gamma_c; inv_gamma_cm1 = 1d / (gamma_c - 1d); Cp_c = inletTherm.Cp; Cv_c = inletTherm.Cv; R_c = inletTherm.R; eair0 = ambientTherm.SpeedOfSound(0d); M0 = vel / eair0; }
/// <summary> /// Sets the freestream properties to static conditions : sea level and not moving /// </summary> /// <param name="usePlanetarium">Whether to use Planetarium.fetch.Home to get static conditions or use standard Earth conditions</param> /// <param name="overallTPR">Total pressure recovery of inlet</param> protected void SetStaticConditions(bool usePlanetarium = true, double overallTPR = 1d) { EngineThermodynamics ambientTherm = new EngineThermodynamics(); ambientTherm.FromStandardConditions(usePlanetarium); EngineThermodynamics inletTherm = new EngineThermodynamics(); inletTherm.CopyFrom(ambientTherm); inletTherm.P *= overallTPR; SetFreestreamAndInlet(ambientTherm, inletTherm, 0d, 0d, Vector3.zero, true, false); }
protected string GetThrustInfo() { string output = ""; if (engineSolver == null || !(engineSolver is SolverRF)) CreateEngine(); rfSolver.SetEngineStatus(true, true, true); // get stats double pressure = 101.325d, temperature = 288.15d, density = 1.225d; if (Planetarium.fetch != null) { CelestialBody home = Planetarium.fetch.Home; if (home != null) { pressure = home.GetPressure(0d); temperature = home.GetTemperature(0d); density = home.GetDensity(pressure, temperature); } } ambientTherm = new EngineThermodynamics(); ambientTherm.FromAmbientConditions(pressure, temperature, density); inletTherm = new EngineThermodynamics(); inletTherm.CopyFrom(ambientTherm); currentThrottle = 1f; lastPropellantFraction = 1d; bool oldE = EngineIgnited; EngineIgnited = true; rfSolver.UpdateThrustRatio(1d); UpdateFlightCondition(ambientTherm, 0d, Vector3d.zero, 0d, true); double thrustASL = (engineSolver.GetThrust() * 0.001d); if (atmChangeFlow) // If it's a jet { output += "<b>Static Thrust: </b>" + (thrustASL).ToString("0.0##") + " kN" + ThrottleString(); if (useVelCurve) // if thrust changes with mach { float vMin, vMax, tMin, tMax; velCurve.FindMinMaxValue(out vMin, out vMax, out tMin, out tMax); // get the max mult, and thus report maximum thrust possible. output += "\n<b>Max. Thrust: </b>" + (thrustASL* vMax).ToString("0.0##") + " kN Mach " + tMax.ToString("0.#"); } } else { // get stats again double spaceHeight = 131000d; pressure = 0d; density = 0d; if (Planetarium.fetch != null) { CelestialBody home = Planetarium.fetch.Home; if (home != null) { temperature = home.GetTemperature(home.atmosphereDepth + 1d); spaceHeight = home.atmosphereDepth + 1000d; } } else temperature = PhysicsGlobals.SpaceTemperature; ambientTherm.FromAmbientConditions(pressure, temperature, density); UpdateFlightCondition(ambientTherm, spaceHeight, Vector3d.zero, 0d, true); double thrustVac = (engineSolver.GetThrust() * 0.001d); if (thrustASL != thrustVac) { output += (throttleLocked ? "<b>" : "<b>Max. ") + "Thrust (Vac.): </b>" + (thrustVac).ToString("0.0##") + " kN" + ThrottleString() + "\n" + (throttleLocked ? "<b>" : "<b>Max. ") + "Thrust (ASL): </b>" + (thrustASL).ToString("0.0##") + " kN"; } else { output += (throttleLocked ? "<b>" : "<b>Max. ") + "Thrust: </b>" + (thrustVac).ToString("0.0##") + " kN" + ThrottleString(); } } output += "\n"; EngineIgnited = oldE; return output; }
private void FixedUpdate() { if (!HighLogic.LoadedSceneIsFlight || !vessel) { return; } if (vessel.altitude > vessel.mainBody.atmosphereDepth) { return; } int newCount = vessel.Parts.Count; if (partsCount != newCount) { partsCount = newCount; updatePartsList(); } InletArea = 0d; EngineArea = 0d; OverallTPR = 0d; AreaRatio = 0d; for (int j = engineList.Count - 1; j >= 0; --j) { ModuleEnginesSolver e = engineList[j]; if ((object)e != null && e.EngineIgnited) { EngineArea += e.Need_Area; } } for (int j = inletList.Count - 1; j >= 0; --j) { AJEInlet i = inletList[j]; if ((object)i != null) { double area = i.UsableArea(); InletArea += area; OverallTPR += area * i.overallTPR; } } if (InletArea > 0d) { if (EngineArea > 0d) { AreaRatio = Math.Min(1d, InletArea / EngineArea); OverallTPR /= InletArea; OverallTPR *= AreaRatio; } else { AreaRatio = 1d; } } AmbientTherm.FromVesselAmbientConditions(vessel); Mach = vessel.mach; // Transform from static frame to vessel frame, increasing total pressure and temperature if (vessel.srfSpeed < 0.01d) { InletTherm.CopyFrom(AmbientTherm); } else { InletTherm.FromChangeReferenceFrame(AmbientTherm, vessel.srfSpeed); } InletTherm.P *= OverallTPR; // TPR accounts for loss of total pressure by inlet // Push parameters to each engine for (int i = engineList.Count - 1; i >= 0; --i) { engineList[i].UpdateInletEffects(InletTherm, AreaRatio, OverallTPR); } }
protected string GetStaticThrustInfo(bool primaryField)//TODO WIP { string output = ""; if (engineSolver == null || !(engineSolver is SolverDEV)) CreateEngine(); SolverDEV devSolver = (engineSolver as SolverDEV); devSolver.SetEngineStatus(true, true, true); // get stats double pressure = 101.325d, temperature = 288.15d, density = 1.225d; if (Planetarium.fetch != null) { CelestialBody home = Planetarium.fetch.Home; if (home != null) { pressure = home.GetPressure(0d); temperature = home.GetTemperature(0d); density = home.GetDensity(pressure, temperature); } } currentThrottle = 1f; lastPropellantFraction = 1d; bool oldE = EngineIgnited; EngineIgnited = true; devSolver.UpdateThrustRatio(1d); ambientTherm = new EngineThermodynamics(); ambientTherm.FromAmbientConditions(pressure, temperature, density); inletTherm = new EngineThermodynamics(); inletTherm.CopyFrom(ambientTherm); UpdateFlightCondition(ambientTherm, 0d, Vector3d.zero, 0d, true); double thrust_atm = (devSolver.GetThrust() * 0.001d); double Isp_atm = devSolver.GetIsp(); double Cstar_atm = devSolver.Cstar; double Ct_atm = devSolver.Ct; ambientTherm = new EngineThermodynamics(); ambientTherm.FromAmbientConditions(0d, 4d, 0d); inletTherm = new EngineThermodynamics(); inletTherm.CopyFrom(ambientTherm); UpdateFlightCondition(ambientTherm, 0d, Vector3d.zero, 0d, true); double thrust_vac = (devSolver.GetThrust() * 0.001d); double Isp_vac = devSolver.GetIsp(); double Cstar_vac = devSolver.Cstar; double Ct_vac = devSolver.Ct; double P_vac = devSolver.GetEnginePressure(); double T_vac = devSolver.GetEngineTemp(); ambientTherm = new EngineThermodynamics(); ambientTherm.FromAmbientConditions(pressure * 2, temperature, density * 2); inletTherm = new EngineThermodynamics(); inletTherm.CopyFrom(ambientTherm); UpdateFlightCondition(ambientTherm, 0d, Vector3d.zero, 0d, true); double thrust_2atm = (devSolver.GetThrust() * 0.001d); double Isp_2atm = devSolver.GetIsp(); double Cstar_2atm = devSolver.Cstar; double Ct_2atm = devSolver.Ct; FloatCurve tC = new FloatCurve(); tC.Add(0, (float)Isp_vac); tC.Add(1, (float)Isp_atm); tC.Add(2, (float)Isp_2atm); atmosphereCurve = tC; maxThrust = (float)Math.Max(thrust_vac, thrust_atm); output += "<b>Max. Thrust(<color=#00FF99>ASL</color>/<color=#99CCFF>Vac.</color>):</b> <color=#00FF99>" + thrust_atm.ToString("N2") + "</color><b>/</b><color=#99CCFF>" + thrust_vac.ToString("N1") + "</color>kN "; output += ThrottleString()+"\n"; output += "<b>Isp(<color=#00FF99>ASL</color>/<color=#99CCFF>Vac.</color>):</b> <color=#00FF99>" + Isp_atm.ToString("N2") + "</color><b>/</b><color=#99CCFF>" + Isp_vac.ToString("N2") + "</color>s\n"; output += "<b><color=#0099ff>Ignitions Available: </color></b>" + ignitions + "\n"; output += "<b><color=#0099ff>Max. Burn time: </color></b>" + maxBurnTime + " Sec.\n"; if (!primaryField) { output += "<b>C*(<color=#00FF99>ASL</color>/<color=#99CCFF>Vac.</color>):</b> <color=#00FF99>" + Cstar_atm.ToString("N2") + "</color><b>/</b><color=#99CCFF>" + Cstar_vac.ToString("N2") + "</color>m/s\n"; output += "<b>Ct(<color=#00FF99>ASL</color>/<color=#99CCFF>Vac.</color>):</b> <color=#00FF99>" + Ct_atm.ToString("N2") + "</color><b>/</b><color=#99CCFF>" + Ct_vac.ToString("N2") + "</color>\n"; output += $"<b>Chamber Pressure:\n</b>{P_vac.ToString("N1")}<b>/</b>{nominalPcns.ToString("N1")}kPa\n<b>Chamber Temperature:\n</b>{T_vac.ToString("N1")}<b>/</b>{nominalTcns.ToString("N1")}K\n"; output += $"<b>Nozzle Exit Pressure: </b>{nominalPe} kPa\n<b>Nozzle Throat Area:</b>{At} m^2\n"; } output += "\n"; EngineIgnited = oldE; return output; }
/// <summary> /// Sets the freestream properties to static conditions : sea level and not moving /// </summary> /// <param name="usePlanetarium">Whether to use Planetarium.fetch.Home to get static conditions or use standard Earth conditions</param> /// <param name="overallTPR">Total pressure recovery of inlet</param> protected void SetStaticConditions(bool usePlanetarium = true, double overallTPR = 1d) { EngineThermodynamics ambientTherm = new EngineThermodynamics(); ambientTherm.FromStandardConditions(usePlanetarium); EngineThermodynamics inletTherm = new EngineThermodynamics(); inletTherm.CopyFrom(ambientTherm); inletTherm.P *= overallTPR; SetFreestreamAndInlet(ambientTherm, inletTherm, 0d, 0d, Vector3.zero, true); }