JSBSim Flight Dynamics Model  1.1.11 (13 Feb 2022)
An Open Source Flight Dynamics and Control Software Library in C++
FGTurboProp.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGTurboProp.cpp
4  Author: Jiri "Javky" Javurek
5  based on SimTurbine and Turbine engine from David Culp
6  Date started: 05/14/2004
7  Purpose: This module models a turbo propeller engine.
8 
9  ------------- Copyright (C) 2004 (javky@email.cz) ---------
10 
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU Lesser General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19  details.
20 
21  You should have received a copy of the GNU Lesser General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25  Further information about the GNU Lesser General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27 
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 
31 This class descends from the FGEngine class and models a Turbo propeller engine
32 based on parameters given in the engine config file for this class
33 
34 HISTORY
35 --------------------------------------------------------------------------------
36 05/14/2004 Created
37 02/08/2011 T. Kreitler, added rotor support
38 
39 //JVK (mark)
40 
41 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 INCLUDES
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
44 
45 #include <iostream>
46 #include <sstream>
47 
48 #include "FGTurboProp.h"
49 #include "FGPropeller.h"
50 #include "FGRotor.h"
51 #include "math/FGFunction.h"
52 #include "input_output/FGXMLElement.h"
53 
54 using namespace std;
55 
56 namespace JSBSim {
57 
58 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 CLASS IMPLEMENTATION
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61 
62 FGTurboProp::FGTurboProp(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input)
63  : FGEngine(engine_number, input),
64  ITT_N1(NULL), EnginePowerRPM_N1(NULL), EnginePowerVC(NULL),
65  CombustionEfficiency_N1(NULL)
66 {
67  SetDefaults();
68  Load(exec, el);
69  Debug(0);
70 }
71 
72 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 
75 {
76  delete ITT_N1;
77  delete EnginePowerRPM_N1;
78  if (dynamic_cast<FGTable*>(EnginePowerVC))
79  delete EnginePowerVC;
80  delete CombustionEfficiency_N1;
81  Debug(1);
82 }
83 
84 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 
86 bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
87 {
88  MaxStartingTime = 999999; //very big timeout -> infinite
89  Ielu_max_torque=-1;
90 
91  Element* function_element = el->FindElement("function");
92 
93  while(function_element) {
94  string name = function_element->GetAttributeValue("name");
95  if (name == "EnginePowerVC")
96  function_element->SetAttributeValue("name", string("propulsion/engine[#]/") + name);
97 
98  function_element = el->FindNextElement("function");
99  }
100 
101  FGEngine::Load(exec, el);
102  thrusterType = Thruster->GetType();
103 
104  string property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
105 
106  EnginePowerVC = GetPreFunction(property_prefix+"/EnginePowerVC");
107 
108 
109 // ToDo: Need to make sure units are properly accounted for below.
110 
111  if (el->FindElement("idlen1"))
112  IdleN1 = el->FindElementValueAsNumber("idlen1");
113  if (el->FindElement("maxn1"))
114  MaxN1 = el->FindElementValueAsNumber("maxn1");
115  if (el->FindElement("betarangeend"))
116  BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
117  BetaRangeThrottleEnd = Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
118  if (el->FindElement("reversemaxpower"))
119  ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;
120 
121  if (el->FindElement("maxpower"))
122  MaxPower = el->FindElementValueAsNumber("maxpower");
123  if (el->FindElement("idlefuelflow")) {
124  cerr << el->ReadFrom() << "Note: 'idlefuelflow' is obsolete, "
125  << "use the 'CombustionEfficiency_N1' table instead." << endl;
126  }
127  if (el->FindElement("psfc"))
128  PSFC = el->FindElementValueAsNumber("psfc");
129  if (el->FindElement("n1idle_max_delay"))
130  Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay");
131  if (el->FindElement("maxstartingtime"))
132  MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime");
133  if (el->FindElement("startern1"))
134  StarterN1 = el->FindElementValueAsNumber("startern1");
135  if (el->FindElement("ielumaxtorque"))
136  Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque");
137  if (el->FindElement("itt_delay"))
138  ITT_Delay = el->FindElementValueAsNumber("itt_delay");
139 
140  Element *table_element = el->FindElement("table");
141  FGPropertyManager* PropertyManager = exec->GetPropertyManager();
142 
143  while (table_element) {
144  string name = table_element->GetAttributeValue("name");
145  if (!EnginePowerVC && name == "EnginePowerVC") {
146  // Get a different name for each engines otherwise FGTable::bind() will
147  // complain that the property 'EnginePowerVC' is already bound. This is a
148  // ugly hack but the functionality is obsolete and will be removed some
149  // time in the future.
150  table_element->SetAttributeValue("name", string("propulsion/engine[#]/") + name);
151  EnginePowerVC = new FGTable(PropertyManager, table_element,
152  to_string((int)EngineNumber));
153  table_element->SetAttributeValue("name", name);
154  cerr << table_element->ReadFrom()
155  <<"Note: Using the EnginePowerVC without enclosed <function> tag is deprecated"
156  << endl;
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);
163  } else {
164  cerr << el->ReadFrom() << "Unknown table type: " << name
165  << " in turboprop definition." << endl;
166  }
167  table_element = el->FindNextElement("table");
168  }
169 
170  // Pre-calculations and initializations
171 
172  delay=1;
173  N1_factor = MaxN1 - IdleN1;
174  OilTemp_degK = in.TAT_c + 273.0;
175 
176  // default table based on '9.333 - (N1)/12.0' approximation
177  // gives 430%Fuel at 60%N1
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;
186  }
187 
188  bindmodel(PropertyManager);
189  return true;
190 }
191 
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 // The main purpose of Calculate() is to determine what phase the engine should
194 // be in, then call the corresponding function.
195 
197 {
198  RunPreFunctions();
199 
200  ThrottlePos = in.ThrottlePos[EngineNumber];
201 
202  /* The thruster controls the engine RPM because it encapsulates the gear ratio
203  and other transmission variables */
204  RPM = Thruster->GetEngineRPM();
205  if (thrusterType == FGThruster::ttPropeller) {
206  ((FGPropeller*)Thruster)->SetAdvance(in.PropAdvance[EngineNumber]);
207  ((FGPropeller*)Thruster)->SetFeather(in.PropFeather[EngineNumber]);
208  ((FGPropeller*)Thruster)->SetReverse(Reversed);
209  if (Reversed) {
210  ((FGPropeller*)Thruster)->SetReverseCoef(ThrottlePos);
211  } else {
212  ((FGPropeller*)Thruster)->SetReverseCoef(0.0);
213  }
214 
215  if (Reversed) {
216  if (ThrottlePos < BetaRangeThrottleEnd) {
217  ThrottlePos = 0.0; // idle when in Beta-range
218  } else {
219  // when reversed:
220  ThrottlePos = (ThrottlePos-BetaRangeThrottleEnd)/(1-BetaRangeThrottleEnd) * ReverseMaxPower;
221  }
222  }
223  }
224 
225  // When trimming is finished check if user wants engine OFF or RUNNING
226  if ((phase == tpTrim) && (in.TotalDeltaT > 0)) {
227  if (Running && !Starved) {
228  phase = tpRun;
229  N1 = IdleN1;
230  OilTemp_degK = 366.0;
231  Cutoff = false;
232  } else {
233  phase = tpOff;
234  Cutoff = true;
235  Eng_ITT_degC = in.TAT_c;
236  Eng_Temperature = in.TAT_c;
237  OilTemp_degK = in.TAT_c+273.15;
238  }
239  }
240 
241  if (!Running && Starter) {
242  if (phase == tpOff) {
243  phase = tpSpinUp;
244  if (StartTime < 0) StartTime=0;
245  }
246  }
247  if (!Running && !Cutoff && (N1 > 15.0)) {
248  phase = tpStart;
249  StartTime = -1;
250  }
251  if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
252  if (in.TotalDeltaT == 0) phase = tpTrim;
253  if (Starved) phase = tpOff;
254  if (Condition >= 10) {
255  phase = tpOff;
256  StartTime=-1;
257  }
258 
259  // limiter intervention wanted?
260  if (Ielu_max_torque > 0.0) {
261  double torque = 0.0;
262 
263  if (thrusterType == FGThruster::ttPropeller) {
264  torque = ((FGPropeller*)(Thruster))->GetTorque();
265  } else if (thrusterType == FGThruster::ttRotor) {
266  torque = ((FGRotor*)(Thruster))->GetTorque();
267  }
268 
269  if (Condition < 1) {
270  if ( abs(torque) > Ielu_max_torque && ThrottlePos >= OldThrottle ) {
271  ThrottlePos = OldThrottle - 0.1 * in.TotalDeltaT; //IELU down
272  Ielu_intervent = true;
273  } else if ( Ielu_intervent && ThrottlePos >= OldThrottle) {
274  ThrottlePos = OldThrottle + 0.05 * in.TotalDeltaT; //IELU up
275  Ielu_intervent = true;
276  } else {
277  Ielu_intervent = false;
278  }
279  } else {
280  Ielu_intervent = false;
281  }
282  OldThrottle = ThrottlePos;
283  }
284 
285  switch (phase) {
286  case tpOff: HP = Off(); break;
287  case tpRun: HP = Run(); break;
288  case tpSpinUp: HP = SpinUp(); break;
289  case tpStart: HP = Start(); break;
290  default: HP = 0;
291  }
292 
293  LoadThrusterInputs();
294  // Filters out negative powers when the propeller is not rotating.
295  double power = HP * hptoftlbssec;
296  if (RPM <= 0.1) power = max(power, 0.0);
297  Thruster->Calculate(power);
298 
299  RunPostFunctions();
300 }
301 
302 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 
304 double FGTurboProp::Off(void)
305 {
306  Running = false; EngStarting = false;
307 
308  FuelFlow_pph = Seek(&FuelFlow_pph, 0, 800.0, 800.0);
309 
310  //allow the air turn with generator
311  N1 = ExpSeek(&N1, in.qbar/15.0, Idle_Max_Delay*2.5, Idle_Max_Delay * 5);
312 
313  OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + in.TAT_c, 400 , 400);
314 
315  Eng_Temperature = ExpSeek(&Eng_Temperature,in.TAT_c,300,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);
318 
319  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
320 
321  if (RPM>5) return -0.012; // friction in engine when propeller spining (estimate)
322  return 0.0;
323 }
324 
325 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 
327 double FGTurboProp::Run(void)
328 {
329  double EngPower_HP;
330 
331  Running = true; Starter = false; EngStarting = false;
332 
333 //---
334  double old_N1 = N1;
335  N1 = ExpSeek(&N1, IdleN1 + ThrottlePos * N1_factor, Idle_Max_Delay, Idle_Max_Delay * 2.4);
336 
337  EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
338  EngPower_HP *= EnginePowerVC->GetValue();
339  if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
340 
341  CombustionEfficiency = CombustionEfficiency_N1->GetValue(N1);
342  FuelFlow_pph = PSFC / CombustionEfficiency * EngPower_HP;
343 
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);
347 
348  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
349 //---
350 
351  OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
352 
353  if (Cutoff) phase = tpOff;
354  if (Starved) phase = tpOff;
355 
356  return EngPower_HP;
357 }
358 
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 
361 double FGTurboProp::SpinUp(void)
362 {
363  double EngPower_HP;
364  Running = false; EngStarting = true;
365  FuelFlow_pph = 0.0;
366 
367  if (!GeneratorPower) {
368  EngStarting=false;
369  phase=tpOff;
370  StartTime = -1;
371  return 0.0;
372  }
373 
374  N1 = ExpSeek(&N1, StarterN1, Idle_Max_Delay * 6, Idle_Max_Delay * 2.4);
375 
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);
379 
380  OilTemp_degK = ExpSeek(&OilTemp_degK,273.15 + in.TAT_c, 400 , 400);
381 
382  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
383 
384  EngPower_HP = EnginePowerRPM_N1->GetValue(RPM,N1);
385  EngPower_HP *= EnginePowerVC->GetValue();
386  if (EngPower_HP > MaxPower) EngPower_HP = MaxPower;
387 
388  if (StartTime>=0) StartTime+=in.TotalDeltaT;
389  if (StartTime > MaxStartingTime && MaxStartingTime > 0) { //start failed due timeout
390  phase = tpOff;
391  StartTime = -1;
392  }
393 
394  return EngPower_HP;
395 }
396 
397 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 
399 double FGTurboProp::Start(void)
400 {
401  double EngPower_HP = 0.0;
402 
403  EngStarting = false;
404  if ((N1 > 15.0) && !Starved) { // minimum 15% N1 needed for start
405  double old_N1 = N1;
406  Cranking = true; // provided for sound effects signal
407  if (N1 < IdleN1) {
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);
417 
418  OilPressure_psi = (N1/100.0*0.25+(0.1-(OilTemp_degK-273.15)*0.1/80.0)*N1/100.0) / 7692.0e-6; //from MPa to psi
419  OilTemp_degK = Seek(&OilTemp_degK, 353.15, 0.4-N1*0.001, 0.04);
420 
421  } else {
422  phase = tpRun;
423  Running = true;
424  Starter = false;
425  Cranking = false;
426  FuelFlow_pph = 0;
427  }
428  } else { // no start if N1 < 15% or Starved
429  phase = tpOff;
430  Starter = false;
431  }
432 
433  return EngPower_HP;
434 }
435 
436 
437 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 
440 {
441  FuelFlowRate = FuelFlow_pph / 3600.0;
442  FuelExpended = FuelFlowRate * in.TotalDeltaT;
443  if (!Starved) FuelUsedLbs += FuelExpended;
444  return FuelExpended;
445 }
446 
447 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 
449 double FGTurboProp::Seek(double *var, double target, double accel, double decel)
450 {
451  double v = *var;
452  if (v > target) {
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;
458  }
459  return v;
460 }
461 
462 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463 
464 double FGTurboProp::ExpSeek(double *var, double target, double accel_tau, double decel_tau)
465 {
466 // exponential delay instead of the linear delay used in Seek
467  double v = *var;
468  if (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;
472  }
473  return v;
474 }
475 
476 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 
478 void FGTurboProp::SetDefaults(void)
479 {
480 // Name = "Not defined";
481  N1 = 0.0;
482  HP = 0.0;
483  Type = etTurboprop;
484  IdleN1 = 30.0;
485  MaxN1 = 100.0;
486  Reversed = false;
487  Cutoff = true;
488  phase = tpOff;
489  Eng_ITT_degC = 0.0;
490 
491  GeneratorPower=true;
492  Condition = 0;
493  Ielu_intervent=false;
494 
495  Idle_Max_Delay = 1.0;
496 
497  ThrottlePos = OldThrottle = 0.0;
498  ITT_Delay = 0.05;
499  ReverseMaxPower = 0.0;
500  BetaRangeThrottleEnd = 0.0;
501  CombustionEfficiency = 1.0;
502 }
503 
504 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 
506 
507 string FGTurboProp::GetEngineLabels(const string& delimiter)
508 {
509  std::ostringstream buf;
510 
511  buf << Name << "_N1[" << EngineNumber << "]" << delimiter
512  << Name << "_PwrAvail[" << EngineNumber << "]" << delimiter
513  << Thruster->GetThrusterLabels(EngineNumber, delimiter);
514 
515  return buf.str();
516 }
517 
518 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 
520 string FGTurboProp::GetEngineValues(const string& delimiter)
521 {
522  std::ostringstream buf;
523 
524  buf << N1 << delimiter
525  << HP << delimiter
526  << Thruster->GetThrusterValues(EngineNumber,delimiter);
527 
528  return buf.str();
529 }
530 
531 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 
533 int FGTurboProp::InitRunning(void)
534 {
535  double dt = in.TotalDeltaT;
536  in.TotalDeltaT = 0.0;
537  Cutoff=false;
538  Running=true;
539  Calculate();
540  in.TotalDeltaT = dt;
541  return phase==tpRun;
542 }
543 
544 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
545 
546 void FGTurboProp::bindmodel(FGPropertyManager* PropertyManager)
547 {
548  string property_name, base_property_name;
549  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
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);
564 }
565 
566 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 // The bitmasked value choices are as follows:
568 // unset: In this case (the default) JSBSim would only print
569 // out the normally expected messages, essentially echoing
570 // the config files as they are read. If the environment
571 // variable is not set, debug_lvl is set to 1 internally
572 // 0: This requests JSBSim not to output any messages
573 // whatsoever.
574 // 1: This value explicity requests the normal JSBSim
575 // startup messages
576 // 2: This value asks for a message to be printed out when
577 // a class is instantiated
578 // 4: When this value is set, a message is displayed when a
579 // FGModel object executes its Run() method
580 // 8: When this value is set, various runtime state variables
581 // are printed out periodically
582 // 16: When set various parameters are sanity checked and
583 // a message is printed out when they go out of bounds
584 
585 void FGTurboProp::Debug(int from)
586 {
587  if (debug_lvl <= 0) return;
588 
589  if (debug_lvl & 1) { // Standard console startup message output
590  if (from == 0) { // Constructor
591 
592  }
593  if (from == 2) { // called from Load()
594  cout << "\n ****MUJ MOTOR TURBOPROP****\n";
595  cout << "\n Engine Name: " << Name << endl;
596  cout << " IdleN1: " << IdleN1 << endl;
597  cout << " MaxN1: " << MaxN1 << endl;
598 
599  cout << endl;
600  }
601  }
602  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
603  if (from == 0) cout << "Instantiated: FGTurboProp" << endl;
604  if (from == 1) cout << "Destroyed: FGTurboProp" << endl;
605  }
606  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
607  }
608  if (debug_lvl & 8 ) { // Runtime state variables
609  }
610  if (debug_lvl & 16) { // Sanity checking
611  }
612  if (debug_lvl & 64) {
613  if (from == 0) { // Constructor
614  }
615  }
616 }
617 }
JSBSim::FGFDMExec
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:185
JSBSim::Element::GetAttributeValue
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Definition: FGXMLElement.cpp:260
JSBSim::FGPropeller
FGPropeller models a propeller given the tabular data for Ct (thrust) and Cp (power),...
Definition: FGPropeller.h:169
JSBSim::Element::FindElement
Element * FindElement(const std::string &el="")
Searches for a specified element.
Definition: FGXMLElement.cpp:389
JSBSim::Element::FindElementValueAsNumber
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
Definition: FGXMLElement.cpp:429
JSBSim::FGTurboProp::Calculate
void Calculate(void)
Calculates the thrust of the engine, and other engine functions.
Definition: FGTurboProp.cpp:196
JSBSim::FGTable
Lookup table class.
Definition: FGTable.h:233
JSBSim::FGFDMExec::GetPropertyManager
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
Definition: FGFDMExec.cpp:1121
JSBSim::FGTurboProp::CalcFuelNeed
double CalcFuelNeed(void)
The fuel need is calculated based on power levels and flow rate for that power level.
Definition: FGTurboProp.cpp:439
JSBSim::FGTurboProp::~FGTurboProp
~FGTurboProp()
Destructor.
Definition: FGTurboProp.cpp:74
JSBSim::Element::SetAttributeValue
bool SetAttributeValue(const std::string &key, const std::string &value)
Modifies an attribute.
Definition: FGXMLElement.cpp:268
JSBSim::FGRotor
Models a helicopter rotor.
Definition: FGRotor.h:235
JSBSim::FGJSBBase::Constrain
static constexpr double Constrain(double min, double value, double max)
Constrain a value between a minimum and a maximum value.
Definition: FGJSBBase.h:333
JSBSim::FGEngine::Inputs
Definition: FGEngine.h:106
JSBSim::Element::ReadFrom
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
Definition: FGXMLElement.cpp:738
JSBSim::Element::FindNextElement
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
Definition: FGXMLElement.cpp:407
JSBSim::FGEngine
Base class for all engines.
Definition: FGEngine.h:103
JSBSim::Element
Definition: FGXMLElement.h:143
JSBSim::FGModelFunctions::GetPreFunction
FGFunction * GetPreFunction(const std::string &name)
Get one of the "pre" function.
Definition: FGModelFunctions.cpp:141