FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Inputs& input) : FGEngine(exec, el, engine_number, input), R_air(287.3), // Gas constant for air J/Kg/K rho_fuel(800), // estimate calorific_value_fuel(47.3e6), // J/Kg Cp_air(1005), // Specific heat (constant pressure) J/Kg/K Cp_fuel(1700), standard_pressure(101320.73) { Element *table_element; string token; string name=""; // Defaults and initializations Type = etPiston; // These items are read from the configuration file // Defaults are from a Lycoming O-360, more or less Cycles = 4; IdleRPM = 600; MaxRPM = 2800; Displacement = 360; SparkFailDrop = 1.0; MaxHP = 200; MinManifoldPressure_inHg = 6.5; MaxManifoldPressure_inHg = 28.5; ManifoldPressureLag=1.0; ISFC = -1; volumetric_efficiency = 0.85; Bore = 5.125; Stroke = 4.375; Cylinders = 4; CylinderHeadMass = 2; //kg CompressionRatio = 8.5; Z_airbox = -999; Ram_Air_Factor = 1; PeakMeanPistonSpeed_fps = 100; FMEPDynamic= 18400; FMEPStatic = 46500; Cooling_Factor = 0.5144444; StaticFriction_HP = 1.5; StarterGain = 1.; StarterTorque = -1.; StarterRPM = -1.; // These are internal program variables Lookup_Combustion_Efficiency = 0; Mixture_Efficiency_Correlation = 0; crank_counter = 0; Magnetos = 0; minMAP = 21950; maxMAP = 96250; ResetToIC(); // Supercharging BoostSpeeds = 0; // Default to no supercharging BoostSpeed = 0; Boosted = false; BoostOverride = 0; BoostManual = 0; bBoostOverride = false; bTakeoffBoost = false; TakeoffBoost = 0.0; // Default to no extra takeoff-boost int i; for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) { RatedBoost[i] = 0.0; RatedPower[i] = 0.0; RatedAltitude[i] = 0.0; BoostMul[i] = 1.0; RatedMAP[i] = 100000; RatedRPM[i] = 2500; TakeoffMAP[i] = 100000; } for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) { BoostSwitchAltitude[i] = 0.0; BoostSwitchPressure[i] = 0.0; } // Read inputs from engine data file where present. if (el->FindElement("minmp")) MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG"); if (el->FindElement("maxmp")) MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG"); if (el->FindElement("man-press-lag")) ManifoldPressureLag = el->FindElementValueAsNumber("man-press-lag"); if (el->FindElement("displacement")) Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3"); if (el->FindElement("maxhp")) MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP"); if (el->FindElement("static-friction")) StaticFriction_HP = el->FindElementValueAsNumberConvertTo("static-friction","HP"); if (el->FindElement("sparkfaildrop")) SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1); if (el->FindElement("cycles")) Cycles = el->FindElementValueAsNumber("cycles"); if (el->FindElement("idlerpm")) IdleRPM = el->FindElementValueAsNumber("idlerpm"); if (el->FindElement("maxrpm")) MaxRPM = el->FindElementValueAsNumber("maxrpm"); if (el->FindElement("maxthrottle")) MaxThrottle = el->FindElementValueAsNumber("maxthrottle"); if (el->FindElement("minthrottle")) MinThrottle = el->FindElementValueAsNumber("minthrottle"); if (el->FindElement("bsfc")) ISFC = el->FindElementValueAsNumberConvertTo("bsfc", "LBS/HP*HR"); if (el->FindElement("volumetric-efficiency")) volumetric_efficiency = el->FindElementValueAsNumber("volumetric-efficiency"); if (el->FindElement("compression-ratio")) CompressionRatio = el->FindElementValueAsNumber("compression-ratio"); if (el->FindElement("bore")) Bore = el->FindElementValueAsNumberConvertTo("bore","IN"); if (el->FindElement("stroke")) Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN"); if (el->FindElement("cylinders")) Cylinders = el->FindElementValueAsNumber("cylinders"); if (el->FindElement("cylinder-head-mass")) CylinderHeadMass = el->FindElementValueAsNumberConvertTo("cylinder-head-mass","KG"); if (el->FindElement("air-intake-impedance-factor")) Z_airbox = el->FindElementValueAsNumber("air-intake-impedance-factor"); if (el->FindElement("ram-air-factor")) Ram_Air_Factor = el->FindElementValueAsNumber("ram-air-factor"); if (el->FindElement("cooling-factor")) Cooling_Factor = el->FindElementValueAsNumber("cooling-factor"); if (el->FindElement("starter-rpm")) StarterRPM = el->FindElementValueAsNumber("starter-rpm"); if (el->FindElement("starter-torque")) StarterTorque = el->FindElementValueAsNumber("starter-torque"); if (el->FindElement("dynamic-fmep")) FMEPDynamic= el->FindElementValueAsNumberConvertTo("dynamic-fmep","PA"); if (el->FindElement("static-fmep")) FMEPStatic = el->FindElementValueAsNumberConvertTo("static-fmep","PA"); if (el->FindElement("peak-piston-speed")) PeakMeanPistonSpeed_fps = el->FindElementValueAsNumber("peak-piston-speed"); if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds"); if (el->FindElement("boostoverride")) BoostOverride = (int)el->FindElementValueAsNumber("boostoverride"); if (el->FindElement("boostmanual")) BoostManual = (int)el->FindElementValueAsNumber("boostmanual"); if (el->FindElement("takeoffboost")) TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI"); if (el->FindElement("ratedboost1")) RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI"); if (el->FindElement("ratedboost2")) RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI"); if (el->FindElement("ratedboost3")) RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI"); if (el->FindElement("ratedpower1")) RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP"); if (el->FindElement("ratedpower2")) RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP"); if (el->FindElement("ratedpower3")) RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP"); if (el->FindElement("ratedrpm1")) RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1"); if (el->FindElement("ratedrpm2")) RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2"); if (el->FindElement("ratedrpm3")) RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3"); if (el->FindElement("ratedaltitude1")) RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT"); if (el->FindElement("ratedaltitude2")) RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT"); if (el->FindElement("ratedaltitude3")) RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT"); } while((table_element = el->FindNextElement("table")) != 0) { name = table_element->GetAttributeValue("name"); try { if (name == "COMBUSTION") { Lookup_Combustion_Efficiency = new FGTable(PropertyManager, table_element); } else if (name == "MIXTURE") { Mixture_Efficiency_Correlation = new FGTable(PropertyManager, table_element); } else { cerr << "Unknown table type: " << name << " in piston engine definition." << endl; } } catch (std::string str) { throw("Error loading piston engine table:" + name + ". " + str); } } volumetric_efficiency_reduced = volumetric_efficiency; if(StarterRPM < 0.) StarterRPM = 2*IdleRPM; if(StarterTorque < 0) StarterTorque = (MaxHP)*0.4; //just a wag. displacement_SI = Displacement * in3tom3; RatedMeanPistonSpeed_fps = ( MaxRPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS // Create IFSC to match the engine if not provided if (ISFC < 0) { double pmep = 29.92 - MaxManifoldPressure_inHg; pmep *= inhgtopa * volumetric_efficiency; double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic); double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371); ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss-StaticFriction_HP)); // cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl; } if ( MaxManifoldPressure_inHg > 29.9 ) { // Don't allow boosting with a bogus number MaxManifoldPressure_inHg = 29.9; } minMAP = MinManifoldPressure_inHg * inhgtopa; // inHg to Pa maxMAP = MaxManifoldPressure_inHg * inhgtopa; // For throttle /* * Pm = ( Ze / ( Ze + Zi + Zt ) ) * Pa * Where: * Pm = Manifold Pressure * Pa = Ambient Pressre * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed * Zi = airbox impedance * Zt = throttle impedance * * For the calculation below throttle is fully open or Zt = 0 * * * */ if(Z_airbox < 0.0){ double Ze=PeakMeanPistonSpeed_fps/RatedMeanPistonSpeed_fps; // engine impedence Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox } // Constant for Throttle impedence Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; // Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence // Default tables if not provided in the configuration file if(Lookup_Combustion_Efficiency == 0) { // First column is thi, second is neta (combustion efficiency) Lookup_Combustion_Efficiency = new FGTable(12); *Lookup_Combustion_Efficiency << 0.00 << 0.980; *Lookup_Combustion_Efficiency << 0.90 << 0.980; *Lookup_Combustion_Efficiency << 1.00 << 0.970; *Lookup_Combustion_Efficiency << 1.05 << 0.950; *Lookup_Combustion_Efficiency << 1.10 << 0.900; *Lookup_Combustion_Efficiency << 1.15 << 0.850; *Lookup_Combustion_Efficiency << 1.20 << 0.790; *Lookup_Combustion_Efficiency << 1.30 << 0.700; *Lookup_Combustion_Efficiency << 1.40 << 0.630; *Lookup_Combustion_Efficiency << 1.50 << 0.570; *Lookup_Combustion_Efficiency << 1.60 << 0.525; *Lookup_Combustion_Efficiency << 2.00 << 0.345; } // First column is Fuel/Air Ratio, second is neta (mixture efficiency) if( Mixture_Efficiency_Correlation == 0) { Mixture_Efficiency_Correlation = new FGTable(15); *Mixture_Efficiency_Correlation << 0.05000 << 0.00000; *Mixture_Efficiency_Correlation << 0.05137 << 0.00862; *Mixture_Efficiency_Correlation << 0.05179 << 0.21552; *Mixture_Efficiency_Correlation << 0.05430 << 0.48276; *Mixture_Efficiency_Correlation << 0.05842 << 0.70690; *Mixture_Efficiency_Correlation << 0.06312 << 0.83621; *Mixture_Efficiency_Correlation << 0.06942 << 0.93103; *Mixture_Efficiency_Correlation << 0.07786 << 1.00000; *Mixture_Efficiency_Correlation << 0.08845 << 1.00000; *Mixture_Efficiency_Correlation << 0.09270 << 0.98276; *Mixture_Efficiency_Correlation << 0.10120 << 0.93103; *Mixture_Efficiency_Correlation << 0.11455 << 0.72414; *Mixture_Efficiency_Correlation << 0.12158 << 0.45690; *Mixture_Efficiency_Correlation << 0.12435 << 0.23276; *Mixture_Efficiency_Correlation << 0.12500 << 0.00000; } string property_name, base_property_name; base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); property_name = base_property_name + "/power-hp"; PropertyManager->Tie(property_name, &HP); property_name = base_property_name + "/bsfc-lbs_hphr"; PropertyManager->Tie(property_name, &ISFC); property_name = base_property_name + "/starter-norm"; PropertyManager->Tie(property_name, &StarterGain); property_name = base_property_name + "/volumetric-efficiency"; PropertyManager->Tie(property_name, &volumetric_efficiency); property_name = base_property_name + "/map-pa"; PropertyManager->Tie(property_name, &MAP); property_name = base_property_name + "/map-inhg"; PropertyManager->Tie(property_name, &ManifoldPressure_inHg); property_name = base_property_name + "/air-intake-impedance-factor"; PropertyManager->Tie(property_name, &Z_airbox); property_name = base_property_name + "/ram-air-factor"; PropertyManager->Tie(property_name, &Ram_Air_Factor); property_name = base_property_name + "/cooling-factor"; PropertyManager->Tie(property_name, &Cooling_Factor); property_name = base_property_name + "/boost-speed"; PropertyManager->Tie(property_name, &BoostSpeed); property_name = base_property_name + "/cht-degF"; PropertyManager->Tie(property_name, this, &FGPiston::getCylinderHeadTemp_degF); property_name = base_property_name + "/oil-temperature-degF"; PropertyManager->Tie(property_name, this, &FGPiston::getOilTemp_degF); property_name = base_property_name + "/oil-pressure-psi"; PropertyManager->Tie(property_name, this, &FGPiston::getOilPressure_psi); property_name = base_property_name + "/egt-degF"; PropertyManager->Tie(property_name, this, &FGPiston::getExhaustGasTemp_degF); // Set up and sanity-check the turbo/supercharging configuration based on the input values. if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true; for (i=0; i<BoostSpeeds; ++i) { bool bad = false; if (RatedBoost[i] <= 0.0) bad = true; if (RatedPower[i] <= 0.0) bad = true; if (RatedAltitude[i] < 0.0) bad = true; // 0.0 is deliberately allowed - this corresponds to unregulated supercharging. if (i > 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true; if (bad) { // We can't recover from the above - don't use this supercharger speed. BoostSpeeds--; // TODO - put out a massive error message! break; } // Now sanity-check stuff that is recoverable. if (i < BoostSpeeds - 1) { if (BoostSwitchAltitude[i] < RatedAltitude[i]) { // TODO - put out an error message // But we can also make a reasonable estimate, as below. BoostSwitchAltitude[i] = RatedAltitude[i] + 1000; } BoostSwitchPressure[i] = GetStdPressure100K(BoostSwitchAltitude[i]) * psftopa; //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n'; // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now BoostSwitchHysteresis = 1000; } // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude. RatedMAP[i] = standard_pressure + RatedBoost[i] * 6895; // psi*6895 = Pa. // Sometimes a separate BCV setting for takeoff or extra power is fitted. if (TakeoffBoost > RatedBoost[0]) { // Assume that the effect on the BCV is the same whichever speed is in use. TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895); bTakeoffBoost = true; } else { TakeoffMAP[i] = RatedMAP[i]; bTakeoffBoost = false; } BoostMul[i] = RatedMAP[i] / (GetStdPressure100K(RatedAltitude[i]) * psftopa); } if (BoostSpeeds > 0) { Boosted = true; BoostSpeed = 0; } bBoostOverride = (BoostOverride == 1 ? true : false); bBoostManual = (BoostManual == 1 ? true : false); Debug(0); // Call Debug() routine from constructor if needed }
FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number, struct Inputs& input) : in(input), EngineNumber(engine_number) { Element* local_element; FGColumnVector3 location, orientation; Name = ""; Type = etUnknown; X = Y = Z = 0.0; EnginePitch = EngineYaw = 0.0; SLFuelFlowMax = 0.0; FuelExpended = 0.0; MaxThrottle = 1.0; MinThrottle = 0.0; ResetToIC(); // initialize dynamic terms FDMExec = exec; PropertyManager = FDMExec->GetPropertyManager(); Name = engine_element->GetAttributeValue("name"); Load(engine_element, PropertyManager, to_string(EngineNumber)); // Call ModelFunctions loader // Find and set engine location local_element = engine_element->GetParent()->FindElement("location"); if (local_element) location = local_element->FindElementTripletConvertTo("IN"); else cerr << "No engine location found for this engine." << endl; local_element = engine_element->GetParent()->FindElement("orient"); if (local_element) orientation = local_element->FindElementTripletConvertTo("RAD"); // else cerr << "No engine orientation found for this engine." << endl; // Jon: The engine orientation has a default and is not normally used. SetPlacement(location, orientation); // Load thruster local_element = engine_element->GetParent()->FindElement("thruster"); if (local_element) { try { if (!LoadThruster(local_element)) exit(-1); } catch (std::string str) { throw("Error loading engine " + Name + ". " + str); } } else { cerr << "No thruster definition supplied with engine definition." << endl; } // Load feed tank[s] references local_element = engine_element->GetParent()->FindElement("feed"); while (local_element) { int tankID = (int)local_element->GetDataAsNumber(); SourceTanks.push_back(tankID); local_element = engine_element->GetParent()->FindNextElement("feed"); } string property_name, base_property_name; base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber); property_name = base_property_name + "/set-running"; PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetRunning, &FGEngine::SetRunning ); property_name = base_property_name + "/thrust-lbs"; PropertyManager->Tie( property_name.c_str(), Thruster, &FGThruster::GetThrust); property_name = base_property_name + "/fuel-flow-rate-pps"; PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRate); property_name = base_property_name + "/fuel-flow-rate-gph"; PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelFlowRateGPH); property_name = base_property_name + "/fuel-used-lbs"; PropertyManager->Tie( property_name.c_str(), this, &FGEngine::GetFuelUsedLbs); PostLoad(engine_element, PropertyManager, to_string(EngineNumber)); Debug(0); }
FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMExec) { Element* thruster_element = el->GetParent(); Element* element; FGColumnVector3 location, orientation, pointing; Type = ttDirect; SetTransformType(FGForce::tCustom); Name = el->GetAttributeValue("name"); GearRatio = 1.0; EngineNum = num; FGPropertyManager* PropertyManager = FDMExec->GetPropertyManager(); // Determine the initial location and orientation of this thruster and load the // thruster with this information. element = thruster_element->FindElement("location"); if (element) location = element->FindElementTripletConvertTo("IN"); else cerr << fgred << " No thruster location found." << reset << endl; SetLocation(location); string property_name, base_property_name; base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum); element = thruster_element->FindElement("pointing"); if (element) { // This defines a fixed nozzle that has no public interface property to gimbal or reverse it. pointing = element->FindElementTripletConvertTo("RAD"); // The specification of RAD here is superfluous, // and simply precludes a conversion. mT.InitMatrix(); mT(1,1) = pointing(1); mT(2,1) = pointing(2); mT(3,1) = pointing(3); } else { element = thruster_element->FindElement("orient"); if (element) orientation = element->FindElementTripletConvertTo("RAD"); SetAnglesToBody(orientation); property_name = base_property_name + "/pitch-angle-rad"; PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetPitch, &FGForce::SetPitch); property_name = base_property_name + "/yaw-angle-rad"; PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw); if (el->GetName() == "direct") // this is a direct thruster. At this time // only a direct thruster can be reversed. { property_name = base_property_name + "/reverser-angle-rad"; PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetReverserAngle, &FGThruster::SetReverserAngle); } } ResetToIC(); Debug(0); }
bool FGTurbine::Load(FGFDMExec* exec, Element *el) { Element* function_element = el->FindElement("function"); while(function_element) { string name = function_element->GetAttributeValue("name"); if (name == "IdleThrust" || name == "MilThrust" || name == "AugThrust" || name == "Injection") function_element->SetAttributeValue("name", string("propulsion/engine[#]/") + name); function_element = el->FindNextElement("function"); } FGEngine::Load(exec, el); ResetToIC(); if (el->FindElement("milthrust")) MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS"); if (el->FindElement("maxthrust")) MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS"); if (el->FindElement("bypassratio")) BypassRatio = el->FindElementValueAsNumber("bypassratio"); if (el->FindElement("bleed")) BleedDemand = el->FindElementValueAsNumber("bleed"); if (el->FindElement("tsfc")) TSFC = el->FindElementValueAsNumber("tsfc"); if (el->FindElement("atsfc")) ATSFC = el->FindElementValueAsNumber("atsfc"); if (el->FindElement("idlen1")) IdleN1 = el->FindElementValueAsNumber("idlen1"); if (el->FindElement("idlen2")) IdleN2 = el->FindElementValueAsNumber("idlen2"); if (el->FindElement("maxn1")) MaxN1 = el->FindElementValueAsNumber("maxn1"); if (el->FindElement("maxn2")) MaxN2 = el->FindElementValueAsNumber("maxn2"); if (el->FindElement("n1spinup")) N1_spinup = el->FindElementValueAsNumber("n1spinup"); if (el->FindElement("n2spinup")) N2_spinup = el->FindElementValueAsNumber("n2spinup"); if (el->FindElement("augmented")) Augmented = (int)el->FindElementValueAsNumber("augmented"); if (el->FindElement("augmethod")) AugMethod = (int)el->FindElementValueAsNumber("augmethod"); if (el->FindElement("injected")) Injected = (int)el->FindElementValueAsNumber("injected"); if (el->FindElement("injection-time")){ InjectionTime = el->FindElementValueAsNumber("injection-time"); InjWaterNorm =1.0; } if (el->FindElement("injection-N1-inc")) InjN1increment = el->FindElementValueAsNumber("injection-N1-inc"); if (el->FindElement("injection-N2-inc")) InjN2increment = el->FindElementValueAsNumber("injection-N2-inc"); string property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber); IdleThrustLookup = GetPreFunction(property_prefix+"/IdleThrust"); MilThrustLookup = GetPreFunction(property_prefix+"/MilThrust"); MaxThrustLookup = GetPreFunction(property_prefix+"/AugThrust"); InjectionLookup = GetPreFunction(property_prefix+"/Injection"); // Pre-calculations and initializations delay = 90.0 / (BypassRatio + 3.0); N1_factor = MaxN1 - IdleN1; N2_factor = MaxN2 - IdleN2; OilTemp_degK = in.TAT_c + 273.0; IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate bindmodel(exec->GetPropertyManager()); return true; }