FlightGear next
FGTurbine.cpp
Go to the documentation of this file.
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGTurbine.cpp
4 Author: David Culp
5 Date started: 03/11/2003
6 Purpose: This module models a turbine engine.
7
8 ------------- Copyright (C) 2003 David Culp (daveculp@cox.net) ---------
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22 Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 Further information about the GNU Lesser General Public License can also be found on
25 the world wide web at http://www.gnu.org.
26
27FUNCTIONAL DESCRIPTION
28--------------------------------------------------------------------------------
29
30This class descends from the FGEngine class and models a turbine engine based
31on parameters given in the engine config file for this class
32
33HISTORY
34--------------------------------------------------------------------------------
3503/11/2003 DPC Created
3609/08/2003 DPC Changed Calculate() and added engine phases
37
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
39INCLUDES
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
41
42#include <iostream>
43#include <sstream>
44
45#include "FGFDMExec.h"
46#include "math/FGFunction.h"
47#include "FGTurbine.h"
48#include "FGThruster.h"
50
51using namespace std;
52
53namespace JSBSim {
54
55/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
56CLASS IMPLEMENTATION
57%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
58
59FGTurbine::FGTurbine(FGFDMExec* exec, Element *el, int engine_number, struct Inputs& input)
60 : FGEngine(engine_number, input), FDMExec(exec)
61{
63
64 MilThrust = MaxThrust = 10000.0;
65 TSFC = 0.8;
66 ATSFC = 1.7;
67 IdleN1 = 30.0;
68 IdleN2 = 60.0;
69 MaxN1 = MaxN2 = 100.0;
70 Augmented = AugMethod = Injected = 0;
71 BypassRatio = BleedDemand = 0.0;
72 IdleThrustLookup = MilThrustLookup = MaxThrustLookup = InjectionLookup = 0;
73 N1_spinup = 1.0; N2_spinup = 3.0; IgnitionN1 = 5.21; IgnitionN2 = 25.18; N1_start_rate = 1.4; N2_start_rate = 2.0;
74 N1_spindown = 2.0; N2_spindown = 2.0;
75 InjectionTime = 30.0;
76 InjectionTimer = InjWaterNorm = 0.0;
77 EPR = 1.0;
78 disableWindmill = false;
79
80 Load(exec, el);
81 Debug(0);
82}
83
84//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85
87{
88 // Delete those functions that have requested the construction of a FGSpoolUp
89 // instance. FGModelFunctions will manage the destruction of the other
90 // instances.
91 if (dynamic_cast<FGSpoolUp*>(N1SpoolUp)) delete N1SpoolUp;
92 if (dynamic_cast<FGSpoolUp*>(N1SpoolDown)) delete N1SpoolDown;
93 if (dynamic_cast<FGSpoolUp*>(N2SpoolUp)) delete N2SpoolUp;
94 if (dynamic_cast<FGSpoolUp*>(N2SpoolDown)) delete N2SpoolDown;
95
96 Debug(1);
97}
98
99//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100
102{
103
105
106 N1 = N2 = InjN1increment = InjN2increment = 0.0;
107 N2norm = 0.0;
108 correctedTSFC = TSFC;
109 AugmentCmd = InjWaterNorm = 0.0;
110 InletPosition = NozzlePosition = 1.0;
111 Stalled = Seized = Overtemp = Fire = Augmentation = Injection = Reversed = false;
112 Cutoff = true;
113 phase = tpOff;
114 EGT_degC = in.TAT_c;
115 OilTemp_degK = in.TAT_c + 273.0;
116}
117
118//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119// The main purpose of Calculate() is to determine what phase the engine should
120// be in, then call the corresponding function.
121
123{
124 double thrust;
125
127
128 ThrottlePos = in.ThrottlePos[EngineNumber];
129
130 if (ThrottlePos > 1.0) {
131 AugmentCmd = ThrottlePos - 1.0;
132 ThrottlePos -= AugmentCmd;
133 } else {
134 AugmentCmd = 0.0;
135 }
136
137 // When trimming is finished check if user wants engine OFF or RUNNING
138 if ((phase == tpTrim) && (in.TotalDeltaT > 0)) {
139 if (Running && !Starved) {
140 phase = tpRun;
141 N1_factor = MaxN1 - IdleN1;
142 N2_factor = MaxN2 - IdleN2;
143 N2 = IdleN2 + ThrottlePos * N2_factor;
144 N1 = IdleN1 + ThrottlePos * N1_factor;
145 OilTemp_degK = 366.0;
146 Cutoff = false;
147 } else {
148 phase = tpOff;
149 Cutoff = true;
150 EGT_degC = in.TAT_c;
151 }
152 }
153
154 if (!Running && Cutoff && Starter) {
155 if (phase == tpOff) phase = tpSpinUp;
156 }
157
158 // start
159 if ((Starter == true) || (in.qbar > 30.0)) {
160 if (!Running && !Cutoff && (N2 > 15.0)) phase = tpStart;
161 }
162
163 if (Cutoff && (phase != tpSpinUp)) phase = tpOff;
164 if (in.TotalDeltaT == 0) phase = tpTrim;
165 if (Starved) phase = tpOff;
166 if (Stalled) phase = tpStall;
167 if (Seized) phase = tpSeize;
168
169 switch (phase) {
170 case tpOff: thrust = Off(); break;
171 case tpRun: thrust = Run(); break;
172 case tpSpinUp: thrust = SpinUp(); break;
173 case tpStart: thrust = Start(); break;
174 case tpStall: thrust = Stall(); break;
175 case tpSeize: thrust = Seize(); break;
176 case tpTrim: thrust = Trim(); break;
177 default: thrust = Off();
178 }
179
180 Thruster->Calculate(thrust); // allow thruster to modify thrust (i.e. reversing)
181
183}
184
185//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186
187double FGTurbine::Off(void)
188{
189 Running = false;
190 FuelFlow_pph = Seek(&FuelFlow_pph, 0, 1000.0, 10000.0);
191 // some engines have inlets that close when they are off. So, if a flag is true disable windmilling
192 if (disableWindmill == false) {
193 // Need a small non-zero increment for acceleration otherwise acceleration will be 0 if N1 = 0
194 N1 = Seek(&N1, in.qbar/10.0, N1/2.0 + 0.1, N1/N1_spindown);
195 N2 = Seek(&N2, in.qbar/15.0, N2/2.0 + 0.1, N2/N2_spindown);
196 } else {
197 N1 = Seek(&N1, 0, N1/2.0, N1/N1_spindown);
198 N2 = Seek(&N2, 0, N2/2.0, N2/N2_spindown);
199 }
200 EGT_degC = Seek(&EGT_degC, in.TAT_c, 11.7, 7.3);
201 OilTemp_degK = Seek(&OilTemp_degK, in.TAT_c + 273.0, 0.2, 0.2);
202 OilPressure_psi = N2 * 0.62;
203 NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
204 EPR = Seek(&EPR, 1.0, 0.2, 0.2);
205 Augmentation = false;
206 return 0.0;
207}
208
209//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210
211double FGTurbine::Run()
212{
213 double idlethrust, milthrust, thrust;
214 double T = in.Temperature;
215
216 idlethrust = MilThrust * IdleThrustLookup->GetValue();
217 milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
218
219 Running = true;
220 Starter = false;
221
222 N1_factor = MaxN1 - IdleN1;
223 N2_factor = MaxN2 - IdleN2;
224 if ((Injected == 1) && Injection && (InjWaterNorm > 0)) {
225 N1_factor += InjN1increment;
226 N2_factor += InjN2increment;
227 }
228 N2 = Seek(&N2, IdleN2 + ThrottlePos * N2_factor,
229 N2SpoolUp->GetValue(), N2SpoolDown->GetValue());
230 N1 = Seek(&N1, IdleN1 + ThrottlePos * N1_factor,
231 N1SpoolUp->GetValue(), N1SpoolDown->GetValue());
232 N2norm = (N2 - IdleN2) / N2_factor;
233 thrust = idlethrust + (milthrust * N2norm * N2norm);
234 EGT_degC = in.TAT_c + 363.1 + ThrottlePos * 357.1;
235 OilPressure_psi = N2 * 0.62;
236 OilTemp_degK = Seek(&OilTemp_degK, 366.0, 1.2, 0.1);
237
238 if (!Augmentation) {
239 correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm));
240 FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 10000.0);
241 if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
242 NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
243 thrust = thrust * (1.0 - BleedDemand);
244 EPR = 1.0 + thrust/MilThrust;
245 }
246
247 if (AugMethod == 1) {
248 if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;}
249 else {Augmentation = false;}
250 }
251
252 if ((Augmented == 1) && Augmentation && (AugMethod < 2)) {
253 thrust = MaxThrustLookup->GetValue() * MaxThrust;
254 FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
255 NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
256 }
257
258 if (AugMethod == 2) {
259 if (AugmentCmd > 0.0) {
260 Augmentation = true;
261 double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust;
262 thrust += (tdiff * AugmentCmd);
263 FuelFlow_pph = Seek(&FuelFlow_pph, thrust * ATSFC, 5000.0, 10000.0);
264 NozzlePosition = Seek(&NozzlePosition, 1.0, 0.8, 0.8);
265 } else {
266 Augmentation = false;
267 }
268 }
269
270 if ((Injected == 1) && Injection && (InjWaterNorm > 0.0)) {
271 InjectionTimer += in.TotalDeltaT;
272 if (InjectionTimer < InjectionTime) {
273 thrust = thrust * InjectionLookup->GetValue();
274 InjWaterNorm = 1.0 - (InjectionTimer/InjectionTime);
275 } else {
276 Injection = false;
277 InjWaterNorm = 0.0;
278 }
279 }
280
281 if (Cutoff) phase = tpOff;
282 if (Starved) phase = tpOff;
283
284 return thrust;
285}
286
287//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288
289double FGTurbine::SpinUp(void)
290{
291 Running = false;
292 FuelFlow_pph = 0.0;
293 N2 = Seek(&N2, IgnitionN2, N2_spinup, N2/2.0);
294 N1 = Seek(&N1, IgnitionN1, N1_spinup, N1/2.0);
295 EGT_degC = Seek(&EGT_degC, in.TAT_c, 11.7, 7.3);
296 OilPressure_psi = N2 * 0.62;
297 OilTemp_degK = Seek(&OilTemp_degK, in.TAT_c + 273.0, 0.2, 0.2);
298 EPR = 1.0;
299 NozzlePosition = 1.0;
300 if (Starter == false) phase = tpOff;
301 return 0.0;
302}
303
304//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305
306double FGTurbine::Start(void)
307{
308 if ((N2 > 15.0) && !Starved) { // minimum 15% N2 needed for start
309 Cranking = true; // provided for sound effects signal
310 if (N2 < IdleN2) {
311 N2 = Seek(&N2, IdleN2, N2_start_rate, N2/2.0);
312 N1 = Seek(&N1, IdleN1, N1_start_rate, N1/2.0);
313 EGT_degC = Seek(&EGT_degC, in.TAT_c + 363.1, 21.3, 7.3);
314 FuelFlow_pph = IdleFF * N2 / IdleN2;
315 OilPressure_psi = N2 * 0.62;
316 if ((Starter == false) && (in.qbar < 30.0)) phase = tpOff; // aborted start
317 }
318 else {
319 phase = tpRun;
320 Running = true;
321 Starter = false;
322 Cranking = false;
323 }
324 }
325 else { // no start if N2 < 15%
326 phase = tpOff;
327 Starter = false;
328 }
329
330 return 0.0;
331}
332
333//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334
335double FGTurbine::Stall(void)
336{
337 EGT_degC = in.TAT_c + 903.14;
338 FuelFlow_pph = IdleFF;
339 N1 = Seek(&N1, in.qbar/10.0, 0, N1/10.0);
340 N2 = Seek(&N2, in.qbar/15.0, 0, N2/10.0);
341 if (ThrottlePos < 0.01) {
342 phase = tpRun; // clear the stall with throttle to idle
343 Stalled = false;
344 }
345 return 0.0;
346}
347
348//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349
350double FGTurbine::Seize(void)
351{
352 N2 = 0.0;
353 N1 = Seek(&N1, in.qbar/20.0, 0, N1/15.0);
354 FuelFlow_pph = Cutoff ? 0.0 : IdleFF;
355 OilPressure_psi = 0.0;
356 OilTemp_degK = Seek(&OilTemp_degK, in.TAT_c + 273.0, 0, 0.2);
357 Running = false;
358 return 0.0;
359}
360
361//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362
363double FGTurbine::Trim()
364{
365 double idlethrust = MilThrust * IdleThrustLookup->GetValue();
366 double milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
367 double N2 = IdleN2 + ThrottlePos * N2_factor;
368 double N2norm = (N2 - IdleN2) / N2_factor;
369 double thrust = (idlethrust + (milthrust * N2norm * N2norm))
370 * (1.0 - BleedDemand);
371
372 if (AugMethod == 1) {
373 if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation = true;}
374 else {Augmentation = false;}
375 }
376
377 if ((Augmented == 1) && Augmentation && (AugMethod < 2)) {
378 thrust = MaxThrust * MaxThrustLookup->GetValue();
379 }
380
381 if (AugMethod == 2) {
382 if (AugmentCmd > 0.0) {
383 double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust;
384 thrust += (tdiff * AugmentCmd);
385 }
386 }
387
388 if ((Injected == 1) && Injection) {
389 thrust = thrust * InjectionLookup->GetValue();
390 }
391
392 return thrust;
393}
394
395//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396
398{
399 FuelFlowRate = FuelFlow_pph / 3600.0; // Calculates flow in lbs/sec from lbs/hr
400 FuelExpended = FuelFlowRate * in.TotalDeltaT; // Calculates fuel expended in this time step
402 return FuelExpended;
403}
404
405//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406
408 if( ThrottlePos <= 0.77 )
409 return 64.94*ThrottlePos;
410 else
411 return 217.38*ThrottlePos - 117.38;
412}
413
414//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415
416double FGTurbine::Seek(double *var, double target, double accel, double decel) {
417 double v = *var;
418 if (v > target) {
419 v -= in.TotalDeltaT * decel;
420 if (v < target) v = target;
421 } else if (v < target) {
422 v += in.TotalDeltaT * accel;
423 if (v > target) v = target;
424 }
425 return v;
426}
427
428//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429
430bool FGTurbine::Load(FGFDMExec* exec, Element *el)
431{
432 Element* function_element = el->FindElement("function");
433
434 while(function_element) {
435 string name = function_element->GetAttributeValue("name");
436 if (name == "IdleThrust" || name == "MilThrust" || name == "AugThrust"
437 || name == "Injection" || name == "N1SpoolUp" || name == "N1SpoolDown"
438 || name == "N2SpoolUp" || name == "N2SpoolDown")
439 function_element->SetAttributeValue("name", string("propulsion/engine[#]/") + name);
440
441 function_element = el->FindNextElement("function");
442 }
443
444 FGEngine::Load(exec, el);
445
446 ResetToIC();
447
448 if (el->FindElement("milthrust"))
449 MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS");
450 if (el->FindElement("maxthrust"))
451 MaxThrust = el->FindElementValueAsNumberConvertTo("maxthrust","LBS");
452 if (el->FindElement("bypassratio"))
453 BypassRatio = el->FindElementValueAsNumber("bypassratio");
454 if (el->FindElement("bleed"))
455 BleedDemand = el->FindElementValueAsNumber("bleed");
456 if (el->FindElement("tsfc"))
457 TSFC = el->FindElementValueAsNumber("tsfc");
458 if (el->FindElement("atsfc"))
459 ATSFC = el->FindElementValueAsNumber("atsfc");
460 if (el->FindElement("ignitionn1"))
461 IgnitionN1 = el->FindElementValueAsNumber("ignitionn1");
462 if (el->FindElement("ignitionn2"))
463 IgnitionN2 = el->FindElementValueAsNumber("ignitionn2");
464 if (el->FindElement("idlen1"))
465 IdleN1 = el->FindElementValueAsNumber("idlen1");
466 if (el->FindElement("idlen2"))
467 IdleN2 = el->FindElementValueAsNumber("idlen2");
468 if (el->FindElement("maxn1"))
469 MaxN1 = el->FindElementValueAsNumber("maxn1");
470 if (el->FindElement("maxn2"))
471 MaxN2 = el->FindElementValueAsNumber("maxn2");
472 if (el->FindElement("n1spinup"))
473 N1_spinup = el->FindElementValueAsNumber("n1spinup");
474 if (el->FindElement("n2spinup"))
475 N2_spinup = el->FindElementValueAsNumber("n2spinup");
476 if (el->FindElement("n1startrate"))
477 N1_start_rate = el->FindElementValueAsNumber("n1startrate");
478 if (el->FindElement("n2startrate"))
479 N2_start_rate = el->FindElementValueAsNumber("n2startrate");
480 if (el->FindElement("n1spindown"))
481 N1_spindown = el->FindElementValueAsNumber("n1spindown");
482 if (el->FindElement("n2spindown"))
483 N2_spindown = el->FindElementValueAsNumber("n2spindown");
484 if (el->FindElement("augmented"))
485 Augmented = (int)el->FindElementValueAsNumber("augmented");
486 if (el->FindElement("augmethod"))
487 AugMethod = (int)el->FindElementValueAsNumber("augmethod");
488 if (el->FindElement("injected"))
489 Injected = (int)el->FindElementValueAsNumber("injected");
490 if (el->FindElement("injection-time")){
491 InjectionTime = el->FindElementValueAsNumber("injection-time");
492 InjWaterNorm =1.0;
493 }
494 if (el->FindElement("injection-N1-inc"))
495 InjN1increment = el->FindElementValueAsNumber("injection-N1-inc");
496 if (el->FindElement("injection-N2-inc"))
497 InjN2increment = el->FindElementValueAsNumber("injection-N2-inc");
498 if (el->FindElement("disable-windmill"))
499 disableWindmill = el->FindElementValueAsBoolean("disable-windmill");
500 string property_prefix = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
501
502 IdleThrustLookup = GetPreFunction(property_prefix+"/IdleThrust");
503 MilThrustLookup = GetPreFunction(property_prefix+"/MilThrust");
504 MaxThrustLookup = GetPreFunction(property_prefix+"/AugThrust");
505 InjectionLookup = GetPreFunction(property_prefix+"/Injection");
506
507 // Pre-calculations and initializations
508 N1SpoolUp = GetPreFunction(property_prefix+"/N1SpoolUp");
509 if (!N1SpoolUp)
510 N1SpoolUp = new FGSpoolUp(this, BypassRatio, 1.0);
511
512 N1SpoolDown = GetPreFunction(property_prefix+"/N1SpoolDown");
513 if (!N1SpoolDown)
514 N1SpoolDown = new FGSpoolUp(this, BypassRatio, 2.4);
515
516 N2SpoolUp = GetPreFunction(property_prefix+"/N2SpoolUp");
517 if (!N2SpoolUp)
518 N2SpoolUp = new FGSpoolUp(this, BypassRatio, 1.0);
519
520 N2SpoolDown = GetPreFunction(property_prefix+"/N2SpoolDown");
521 if (!N2SpoolDown)
522 N2SpoolDown = new FGSpoolUp(this, BypassRatio, 3.0);
523
524 N1_factor = MaxN1 - IdleN1;
525 N2_factor = MaxN2 - IdleN2;
526 OilTemp_degK = in.TAT_c + 273.0;
527 IdleFF = pow(MilThrust, 0.2) * 107.0; // just an estimate
528
529 bindmodel(exec->GetPropertyManager());
530 return true;
531}
532
533//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534
535string FGTurbine::GetEngineLabels(const string& delimiter)
536{
537 std::ostringstream buf;
538
539 buf << Name << "_N1[" << EngineNumber << "]" << delimiter
540 << Name << "_N2[" << EngineNumber << "]" << delimiter
541 << Thruster->GetThrusterLabels(EngineNumber, delimiter);
542
543 return buf.str();
544}
545
546//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547
548string FGTurbine::GetEngineValues(const string& delimiter)
549{
550 std::ostringstream buf;
551
552 buf << N1 << delimiter
553 << N2 << delimiter
554 << Thruster->GetThrusterValues(EngineNumber, delimiter);
555
556 return buf.str();
557}
558
559//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560
561void FGTurbine::bindmodel(FGPropertyManager* PropertyManager)
562{
563 string property_name, base_property_name;
564 base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
565 property_name = base_property_name + "/n1";
566 PropertyManager->Tie( property_name.c_str(), &N1);
567 property_name = base_property_name + "/n2";
568 PropertyManager->Tie( property_name.c_str(), &N2);
569 property_name = base_property_name + "/injection_cmd";
570 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
572 property_name = base_property_name + "/seized";
573 PropertyManager->Tie( property_name.c_str(), &Seized);
574 property_name = base_property_name + "/stalled";
575 PropertyManager->Tie( property_name.c_str(), &Stalled);
576 property_name = base_property_name + "/bleed-factor";
577 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this, &FGTurbine::GetBleedDemand, &FGTurbine::SetBleedDemand);
578 property_name = base_property_name + "/MaxN1";
579 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
581 property_name = base_property_name + "/MaxN2";
582 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
584 property_name = base_property_name + "/InjectionTimer";
585 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
587 property_name = base_property_name + "/InjWaterNorm";
588 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
590 property_name = base_property_name + "/InjN1increment";
591 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
593 property_name = base_property_name + "/InjN2increment";
594 PropertyManager->Tie( property_name.c_str(), (FGTurbine*)this,
596}
597
598//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599
601{
602 FDMExec->SuspendIntegration();
603 Cutoff=false;
604 Running=true;
605 N1_factor = MaxN1 - IdleN1;
606 N2_factor = MaxN2 - IdleN2;
607 N2 = IdleN2 + ThrottlePos * N2_factor;
608 N1 = IdleN1 + ThrottlePos * N1_factor;
609 Calculate();
610 FDMExec->ResumeIntegration();
611 return phase=tpRun;
612}
613
614//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
615// The bitmasked value choices are as follows:
616// unset: In this case (the default) JSBSim would only print
617// out the normally expected messages, essentially echoing
618// the config files as they are read. If the environment
619// variable is not set, debug_lvl is set to 1 internally
620// 0: This requests JSBSim not to output any messages
621// whatsoever.
622// 1: This value explicity requests the normal JSBSim
623// startup messages
624// 2: This value asks for a message to be printed out when
625// a class is instantiated
626// 4: When this value is set, a message is displayed when a
627// FGModel object executes its Run() method
628// 8: When this value is set, various runtime state variables
629// are printed out periodically
630// 16: When set various parameters are sanity checked and
631// a message is printed out when they go out of bounds
632
633void FGTurbine::Debug(int from)
634{
635 if (debug_lvl <= 0) return;
636
637 if (debug_lvl & 1) { // Standard console startup message output
638 if (from == 0) { // Constructor
639
640 }
641 if (from == 2) { // called from Load()
642 cout << "\n Engine Name: " << Name << endl;
643 cout << " MilThrust: " << MilThrust << endl;
644 cout << " MaxThrust: " << MaxThrust << endl;
645 cout << " BypassRatio: " << BypassRatio << endl;
646 cout << " TSFC: " << TSFC << endl;
647 cout << " ATSFC: " << ATSFC << endl;
648 cout << " IdleN1: " << IdleN1 << endl;
649 cout << " IdleN2: " << IdleN2 << endl;
650 cout << " MaxN1: " << MaxN1 << endl;
651 cout << " MaxN2: " << MaxN2 << endl;
652 cout << " Augmented: " << Augmented << endl;
653 cout << " AugMethod: " << AugMethod << endl;
654 cout << " Injected: " << Injected << endl;
655 cout << " MinThrottle: " << MinThrottle << endl;
656
657 cout << endl;
658 }
659 }
660 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
661 if (from == 0) cout << "Instantiated: FGTurbine" << endl;
662 if (from == 1) cout << "Destroyed: FGTurbine" << endl;
663 }
664 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
665 }
666 if (debug_lvl & 8 ) { // Runtime state variables
667 }
668 if (debug_lvl & 16) { // Sanity checking
669 }
670 if (debug_lvl & 64) {
671 if (from == 0) { // Constructor
672 }
673 }
674}
675}
double FindElementValueAsNumberConvertTo(const std::string &el, const std::string &target_units)
Searches for the named element and converts and returns the data belonging to it.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
bool FindElementValueAsBoolean(const std::string &el="")
Searches for the named element and returns the data belonging to it as a bool.
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.
EngineType Type
Definition FGEngine.h:204
double FuelExpended
Definition FGEngine.h:209
FGThruster * Thruster
Definition FGEngine.h:223
double FuelFlow_pph
Definition FGEngine.h:219
double FuelFlowRate
Definition FGEngine.h:210
struct Inputs & in
Definition FGEngine.h:197
bool Load(FGFDMExec *exec, Element *el)
Definition FGEngine.cpp:176
const int EngineNumber
Definition FGEngine.h:203
double MinThrottle
Definition FGEngine.h:207
std::string Name
Definition FGEngine.h:202
FGEngine(int engine_number, struct Inputs &input)
Definition FGEngine.cpp:55
double FuelUsedLbs
Definition FGEngine.h:220
virtual void ResetToIC(void)
Resets the Engine parameters to the initial conditions.
Definition FGEngine.cpp:77
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
static short debug_lvl
Definition FGJSBBase.h:190
static std::string CreateIndexedPropertyName(const std::string &Property, int index)
FGFunction * GetPreFunction(const std::string &name)
Get one of the "pre" function.
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
This class models a turbine engine.
Definition FGTurbine.h:155
double GetMaxN1(void) const
Definition FGTurbine.h:202
void SetInjection(bool injection)
Definition FGTurbine.h:211
bool GetInjection(void) const
Definition FGTurbine.h:187
void SetInjectionTimer(double injtimer)
Definition FGTurbine.h:221
void Calculate(void)
Calculates the thrust of the engine, and other engine functions.
FGTurbine(FGFDMExec *Executive, Element *el, int engine_number, struct Inputs &input)
Constructor.
Definition FGTurbine.cpp:59
double GetBleedDemand(void) const
Definition FGTurbine.h:196
double GetInjN2increment(void) const
Definition FGTurbine.h:209
double GetInjectionTimer(void) const
Definition FGTurbine.h:206
void SetInjN1increment(double injN1inc)
Definition FGTurbine.h:223
double GetInjWaterNorm(void) const
Definition FGTurbine.h:207
void ResetToIC(void)
Resets the Engine parameters to the initial conditions.
double Seek(double *var, double target, double accel, double decel)
A lag filter.
void SetMaxN2(double maxn2)
Definition FGTurbine.h:220
friend class FGSpoolUp
Definition FGTurbine.h:310
~FGTurbine()
Destructor.
Definition FGTurbine.cpp:86
std::string GetEngineValues(const std::string &delimiter)
void SetInjWaterNorm(double injwater)
Definition FGTurbine.h:222
void SetMaxN1(double maxn1)
Definition FGTurbine.h:219
double GetMaxN2(void) const
Definition FGTurbine.h:203
void SetInjN2increment(double injN2inc)
Definition FGTurbine.h:224
double CalcFuelNeed(void)
The fuel need is calculated based on power levels and flow rate for that power level.
double GetInjN1increment(void) const
Definition FGTurbine.h:208
int InitRunning(void)
std::string GetEngineLabels(const std::string &delimiter)
void SetBleedDemand(double bleedDemand)
Definition FGTurbine.h:216
double GetPowerAvailable(void)
const char * name
short debug_lvl