60 :
FGEngine(engine_number, input), FDMExec(exec)
64 MilThrust = MaxThrust = 10000.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;
76 InjectionTimer = InjWaterNorm = 0.0;
78 disableWindmill =
false;
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;
106 N1 = N2 = InjN1increment = InjN2increment = 0.0;
108 correctedTSFC = TSFC;
109 AugmentCmd = InjWaterNorm = 0.0;
110 InletPosition = NozzlePosition = 1.0;
111 Stalled = Seized = Overtemp = Fire = Augmentation = Injection = Reversed =
false;
115 OilTemp_degK =
in.TAT_c + 273.0;
130 if (ThrottlePos > 1.0) {
131 AugmentCmd = ThrottlePos - 1.0;
132 ThrottlePos -= AugmentCmd;
138 if ((phase ==
tpTrim) && (
in.TotalDeltaT > 0)) {
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;
159 if ((
Starter ==
true) || (
in.qbar > 30.0)) {
164 if (
in.TotalDeltaT == 0) phase =
tpTrim;
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();
187double FGTurbine::Off(
void)
192 if (disableWindmill ==
false) {
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);
197 N1 =
Seek(&N1, 0, N1/2.0, N1/N1_spindown);
198 N2 =
Seek(&N2, 0, N2/2.0, N2/N2_spindown);
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;
211double FGTurbine::Run()
213 double idlethrust, milthrust, thrust;
214 double T =
in.Temperature;
216 idlethrust = MilThrust * IdleThrustLookup->GetValue();
217 milthrust = (MilThrust - idlethrust) * MilThrustLookup->GetValue();
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;
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);
239 correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm));
242 NozzlePosition =
Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
243 thrust = thrust * (1.0 - BleedDemand);
244 EPR = 1.0 + thrust/MilThrust;
247 if (AugMethod == 1) {
248 if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation =
true;}
249 else {Augmentation =
false;}
252 if ((Augmented == 1) && Augmentation && (AugMethod < 2)) {
253 thrust = MaxThrustLookup->GetValue() * MaxThrust;
255 NozzlePosition =
Seek(&NozzlePosition, 1.0, 0.8, 0.8);
258 if (AugMethod == 2) {
259 if (AugmentCmd > 0.0) {
261 double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust;
262 thrust += (tdiff * AugmentCmd);
264 NozzlePosition =
Seek(&NozzlePosition, 1.0, 0.8, 0.8);
266 Augmentation =
false;
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);
281 if (Cutoff) phase =
tpOff;
289double FGTurbine::SpinUp(
void)
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);
299 NozzlePosition = 1.0;
306double FGTurbine::Start(
void)
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);
315 OilPressure_psi = N2 * 0.62;
335double FGTurbine::Stall(
void)
337 EGT_degC =
in.TAT_c + 903.14;
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) {
350double FGTurbine::Seize(
void)
353 N1 =
Seek(&N1,
in.qbar/20.0, 0, N1/15.0);
355 OilPressure_psi = 0.0;
356 OilTemp_degK =
Seek(&OilTemp_degK,
in.TAT_c + 273.0, 0, 0.2);
363double FGTurbine::Trim()
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);
372 if (AugMethod == 1) {
373 if ((ThrottlePos > 0.99) && (N2 > 97.0)) {Augmentation =
true;}
374 else {Augmentation =
false;}
377 if ((Augmented == 1) && Augmentation && (AugMethod < 2)) {
378 thrust = MaxThrust * MaxThrustLookup->GetValue();
381 if (AugMethod == 2) {
382 if (AugmentCmd > 0.0) {
383 double tdiff = (MaxThrust * MaxThrustLookup->GetValue()) - thrust;
384 thrust += (tdiff * AugmentCmd);
388 if ((Injected == 1) && Injection) {
389 thrust = thrust * InjectionLookup->GetValue();
408 if( ThrottlePos <= 0.77 )
409 return 64.94*ThrottlePos;
411 return 217.38*ThrottlePos - 117.38;
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;
434 while(function_element) {
436 if (
name ==
"IdleThrust" ||
name ==
"MilThrust" ||
name ==
"AugThrust"
437 ||
name ==
"Injection" ||
name ==
"N1SpoolUp" ||
name ==
"N1SpoolDown"
438 ||
name ==
"N2SpoolUp" ||
name ==
"N2SpoolDown")
510 N1SpoolUp =
new FGSpoolUp(
this, BypassRatio, 1.0);
514 N1SpoolDown =
new FGSpoolUp(
this, BypassRatio, 2.4);
518 N2SpoolUp =
new FGSpoolUp(
this, BypassRatio, 1.0);
522 N2SpoolDown =
new FGSpoolUp(
this, BypassRatio, 3.0);
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;
537 std::ostringstream buf;
550 std::ostringstream buf;
552 buf << N1 << delimiter
563 string property_name, base_property_name;
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";
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,
602 FDMExec->SuspendIntegration();
605 N1_factor = MaxN1 - IdleN1;
606 N2_factor = MaxN2 - IdleN2;
607 N2 = IdleN2 + ThrottlePos * N2_factor;
608 N1 = IdleN1 + ThrottlePos * N1_factor;
610 FDMExec->ResumeIntegration();
633void FGTurbine::Debug(
int from)
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;
661 if (from == 0) cout <<
"Instantiated: FGTurbine" << endl;
662 if (from == 1) cout <<
"Destroyed: FGTurbine" << endl;
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.
bool Load(FGFDMExec *exec, Element *el)
FGEngine(int engine_number, struct Inputs &input)
virtual void ResetToIC(void)
Resets the Engine parameters to the initial conditions.
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
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.
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
This class models a turbine engine.
double GetMaxN1(void) const
void SetInjection(bool injection)
bool GetInjection(void) const
void SetInjectionTimer(double injtimer)
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.
double GetBleedDemand(void) const
double GetInjN2increment(void) const
double GetInjectionTimer(void) const
void SetInjN1increment(double injN1inc)
double GetInjWaterNorm(void) const
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)
std::string GetEngineValues(const std::string &delimiter)
void SetInjWaterNorm(double injwater)
void SetMaxN1(double maxn1)
double GetMaxN2(void) const
void SetInjN2increment(double injN2inc)
double CalcFuelNeed(void)
The fuel need is calculated based on power levels and flow rate for that power level.
double GetInjN1increment(void) const
std::string GetEngineLabels(const std::string &delimiter)
void SetBleedDemand(double bleedDemand)
double GetPowerAvailable(void)