64 ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL),
65 CombustionEfficiency_N1(NULL)
77 delete EnginePowerRPM_N1;
78 if (
dynamic_cast<FGTable*
>(EnginePowerVC))
80 delete CombustionEfficiency_N1;
88 MaxStartingTime = 999999;
93 while(function_element) {
95 if (
name ==
"EnginePowerVC")
117 BetaRangeThrottleEnd =
Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
124 cerr << el->
ReadFrom() <<
"Note: 'idlefuelflow' is obsolete, "
125 <<
"use the 'CombustionEfficiency_N1' table instead." << endl;
143 while (table_element) {
145 if (!EnginePowerVC &&
name ==
"EnginePowerVC") {
151 EnginePowerVC =
new FGTable(PropertyManager, table_element,
155 <<
"Note: Using the EnginePowerVC without enclosed <function> tag is deprecated"
157 }
else if (
name ==
"EnginePowerRPM_N1") {
158 EnginePowerRPM_N1 =
new FGTable(PropertyManager, table_element);
159 }
else if (
name ==
"ITT_N1") {
160 ITT_N1 =
new FGTable(PropertyManager, table_element);
161 }
else if (
name ==
"CombustionEfficiency_N1") {
162 CombustionEfficiency_N1 =
new FGTable(PropertyManager, table_element);
164 cerr << el->
ReadFrom() <<
"Unknown table type: " <<
name
165 <<
" in turboprop definition." << endl;
173 N1_factor = MaxN1 - IdleN1;
174 OilTemp_degK =
in.TAT_c + 273.0;
178 if (! CombustionEfficiency_N1) {
179 CombustionEfficiency_N1 =
new FGTable(6);
180 *CombustionEfficiency_N1 << 60.0 << 12.0/52.0;
181 *CombustionEfficiency_N1 << 82.0 << 12.0/30.0;
182 *CombustionEfficiency_N1 << 96.0 << 12.0/16.0;
183 *CombustionEfficiency_N1 << 100.0 << 1.0;
184 *CombustionEfficiency_N1 << 104.0 << 1.5;
185 *CombustionEfficiency_N1 << 110.0 << 6.0;
188 bindmodel(PropertyManager);
216 if (ThrottlePos < BetaRangeThrottleEnd) {
220 ThrottlePos = (ThrottlePos-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
226 if ((phase ==
tpTrim) && (
in.TotalDeltaT > 0)) {
230 OilTemp_degK = 366.0;
235 Eng_ITT_degC =
in.TAT_c;
236 Eng_Temperature =
in.TAT_c;
237 OilTemp_degK =
in.TAT_c+273.15;
242 if (phase ==
tpOff) {
244 if (StartTime < 0) StartTime=0;
247 if (!
Running && !Cutoff && (N1 > 15.0)) {
252 if (
in.TotalDeltaT == 0) phase =
tpTrim;
254 if (Condition >= 10) {
260 if (Ielu_max_torque > 0.0) {
270 if ( abs(torque) > Ielu_max_torque && ThrottlePos >= OldThrottle ) {
271 ThrottlePos = OldThrottle - 0.1 *
in.TotalDeltaT;
272 Ielu_intervent =
true;
273 }
else if ( Ielu_intervent && ThrottlePos >= OldThrottle) {
274 ThrottlePos = OldThrottle + 0.05 *
in.TotalDeltaT;
275 Ielu_intervent =
true;
277 Ielu_intervent =
false;
280 Ielu_intervent =
false;
282 OldThrottle = ThrottlePos;
286 case tpOff: HP = Off();
break;
287 case tpRun: HP = Run();
break;
288 case tpSpinUp: HP = SpinUp();
break;
289 case tpStart: HP = Start();
break;
296 if (RPM <= 0.1) power = max(power, 0.0);
304double FGTurboProp::Off(
void)
306 Running =
false; EngStarting =
false;
311 N1 =
ExpSeek(&N1,
in.
qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5);
313 OilTemp_degK =
ExpSeek(&OilTemp_degK,273.15 +
in.
TAT_c, 400 , 400);
316 double ITT_goal = ITT_N1->
GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature);
317 Eng_ITT_degC =
ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
319 OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6;
321 if (RPM>5)
return -0.012;
327double FGTurboProp::Run(
void)
335 N1 =
ExpSeek(&N1, IdleN1 + ThrottlePos * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
337 EngPower_HP = EnginePowerRPM_N1->
GetValue(RPM,N1);
338 EngPower_HP *= EnginePowerVC->
GetValue();
339 if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
341 CombustionEfficiency = CombustionEfficiency_N1->
GetValue(N1);
342 FuelFlow_pph = PSFC / CombustionEfficiency * EngPower_HP;
344 Eng_Temperature =
ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400);
345 double ITT_goal = ITT_N1->
GetValue((N1-old_N1)*300+N1,1);
346 Eng_ITT_degC =
ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
348 OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6;
351 OilTemp_degK =
Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
353 if (Cutoff) phase =
tpOff;
361double FGTurboProp::SpinUp(
void)
364 Running =
false; EngStarting =
true;
367 if (!GeneratorPower) {
374 N1 =
ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4);
376 Eng_Temperature =
ExpSeek(&Eng_Temperature,
in.TAT_c,300,400);
377 double ITT_goal = ITT_N1->GetValue(N1,0.1) + ((N1>20) ? 0.0 : (20-N1)/20.0 * Eng_Temperature);
378 Eng_ITT_degC =
ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
380 OilTemp_degK =
ExpSeek(&OilTemp_degK,273.15 +
in.TAT_c, 400 , 400);
382 OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6;
384 EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
385 EngPower_HP *= EnginePowerVC->GetValue();
386 if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
388 if (StartTime>=0) StartTime+=
in.TotalDeltaT;
389 if (StartTime > MaxStartingTime && MaxStartingTime > 0) {
399double FGTurboProp::Start(
void)
401 double EngPower_HP = 0.0;
408 EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
409 EngPower_HP *= EnginePowerVC->GetValue();
410 if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
411 N1 =
ExpSeek(&N1, IdleN1*1.1, Idle_Max_Delay*4, Idle_Max_Delay * 2.4);
412 CombustionEfficiency = CombustionEfficiency_N1->GetValue(N1);
413 FuelFlow_pph = PSFC / CombustionEfficiency * EngPower_HP;
414 Eng_Temperature =
ExpSeek(&Eng_Temperature,Eng_ITT_degC,300,400);
415 double ITT_goal = ITT_N1->GetValue((N1-old_N1)*300+N1,1);
416 Eng_ITT_degC =
ExpSeek(&Eng_ITT_degC,ITT_goal,ITT_Delay,ITT_Delay*1.2);
418 OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6;
419 OilTemp_degK =
Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
453 v -=
in.TotalDeltaT * decel;
454 if (v < target) v = target;
455 }
else if (v < target) {
456 v +=
in.TotalDeltaT * accel;
457 if (v > target) v = target;
469 v = (v - target) * exp ( -
in.TotalDeltaT / decel_tau) + target;
470 }
else if (v < target) {
471 v = (target - v) * (1 - exp ( -
in.TotalDeltaT / accel_tau)) + v;
478void FGTurboProp::SetDefaults(
void)
493 Ielu_intervent=
false;
495 Idle_Max_Delay = 1.0;
497 ThrottlePos = OldThrottle = 0.0;
499 ReverseMaxPower = 0.0;
500 BetaRangeThrottleEnd = 0.0;
501 CombustionEfficiency = 1.0;
509 std::ostringstream buf;
522 std::ostringstream buf;
524 buf << N1 << delimiter
535 double dt =
in.TotalDeltaT;
536 in.TotalDeltaT = 0.0;
548 string property_name, base_property_name;
550 property_name = base_property_name +
"/n1";
551 PropertyManager->
Tie( property_name.c_str(), &N1);
552 property_name = base_property_name +
"/reverser";
553 PropertyManager->
Tie( property_name.c_str(), &Reversed);
554 property_name = base_property_name +
"/power-hp";
555 PropertyManager->
Tie( property_name.c_str(), &HP);
556 property_name = base_property_name +
"/itt-c";
557 PropertyManager->
Tie( property_name.c_str(), &Eng_ITT_degC);
558 property_name = base_property_name +
"/engtemp-c";
559 PropertyManager->
Tie( property_name.c_str(), &Eng_Temperature);
560 property_name = base_property_name +
"/ielu_intervent";
561 PropertyManager->
Tie( property_name.c_str(), &Ielu_intervent);
562 property_name = base_property_name +
"/combustion_efficiency";
563 PropertyManager->
Tie( property_name.c_str(), &CombustionEfficiency);
585void FGTurboProp::Debug(
int from)
594 cout <<
"\n ****MUJ MOTOR TURBOPROP****\n";
595 cout <<
"\n Engine Name: " <<
Name << endl;
596 cout <<
" IdleN1: " << IdleN1 << endl;
597 cout <<
" MaxN1: " << MaxN1 << endl;
603 if (from == 0) cout <<
"Instantiated: FGTurboProp" << endl;
604 if (from == 1) cout <<
"Destroyed: FGTurboProp" << endl;
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
bool SetAttributeValue(const std::string &key, const std::string &value)
Modifies an attribute.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
bool SetAttributeValue(const std::string &key, const std::string &value)
Modifies an attribute.
Element * FindElement(const std::string &el="")
Searches for a specified element.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
bool Load(FGFDMExec *exec, Element *el)
void LoadThrusterInputs()
FGEngine(int engine_number, struct Inputs &input)
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
static constexpr double Constrain(double min, double value, double max)
Constrain a value between a minimum and a maximum value.
static constexpr double hptoftlbssec
static std::string CreateIndexedPropertyName(const std::string &Property, int index)
void RunPostFunctions(void)
void RunPreFunctions(void)
FGFunction * GetPreFunction(const std::string &name)
Get one of the "pre" function.
virtual double GetValue(void) const =0
FGPropeller models a propeller given the tabular data for Ct (thrust) and Cp (power),...
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
Models a helicopter rotor.
double GetValue(void) const
double Seek(double *var, double target, double accel, double decel)
double ExpSeek(double *var, double target, double accel, double decel)
void Calculate(void)
Calculates the thrust of the engine, and other engine functions.
std::string GetEngineLabels(const std::string &delimiter)
std::string GetEngineValues(const std::string &delimiter)
double CalcFuelNeed(void)
The fuel need is calculated based on power levels and flow rate for that power level.
FGTurboProp(FGFDMExec *Executive, Element *el, int engine_number, struct Inputs &input)
Constructor.
~FGTurboProp()
Destructor.