]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/FGPropulsion.cpp
ba486d1398054cd57099c124dfa85c83d70820ed
[flightgear.git] / src / FDM / JSBSim / models / FGPropulsion.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGPropulsion.cpp
4  Author:       Jon S. Berndt
5  Date started: 08/20/00
6  Purpose:      Encapsulates the set of engines and tanks associated
7                with this aircraft
8
9  ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) -------------
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 The Propulsion class is the container for the entire propulsion system, which is
31 comprised of engines and tanks. Once the Propulsion class gets the config file,
32 it reads in information which is specific to a type of engine. Then:
33
34 1) The appropriate engine type instance is created
35 2) At least one tank object is created, and is linked to an engine.
36
37 At Run time each engines Calculate() method is called.
38
39 HISTORY
40 --------------------------------------------------------------------------------
41 08/20/00   JSB   Created
42
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 INCLUDES
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46
47 #include "FGPropulsion.h"
48 #include <models/propulsion/FGRocket.h>
49 #include <models/propulsion/FGTurbine.h>
50 #include <models/propulsion/FGPiston.h>
51 #include <models/propulsion/FGElectric.h>
52 #include <models/propulsion/FGTurboProp.h>
53 #include <input_output/FGPropertyManager.h>
54 #include <input_output/FGXMLParse.h>
55 #include <math/FGColumnVector3.h>
56 #include <sstream>
57
58 namespace JSBSim {
59
60 static const char *IdSrc = "$Id$";
61 static const char *IdHdr = ID_PROPULSION;
62
63 extern short debug_lvl;
64
65 using std::ifstream;
66
67 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 CLASS IMPLEMENTATION
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
70
71 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
72 {
73   Name = "FGPropulsion";
74
75   numSelectedFuelTanks = numSelectedOxiTanks = 0;
76   numTanks = numEngines = 0;
77   numOxiTanks = numFuelTanks = 0;
78   ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
79   tankJ.InitMatrix();
80   refuel = false;
81   fuel_freeze = false;
82   TotalFuelQuantity = 0.0;
83   IsBound =
84   HavePistonEngine =
85   HaveTurbineEngine =
86   HaveRocketEngine =
87   HaveTurboPropEngine =
88   HaveElectricEngine = false;
89
90   Debug(0);
91 }
92
93 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94
95 FGPropulsion::~FGPropulsion()
96 {
97   for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
98   Engines.clear();
99   unbind();
100   Debug(1);
101 }
102
103 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104
105 bool FGPropulsion::Run(void)
106 {
107   unsigned int i;
108
109   if (FGModel::Run()) return true;
110   if (FDMExec->Holding()) return false;
111
112   double dt = State->Getdt();
113
114   vForces.InitMatrix();
115   vMoments.InitMatrix();
116
117   for (i=0; i<numEngines; i++) {
118     Engines[i]->Calculate();
119     vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
120     vMoments += Engines[i]->GetMoments();     // sum body frame moments
121   }
122
123   TotalFuelQuantity = 0.0;
124   for (i=0; i<numTanks; i++) {
125     Tanks[i]->Calculate( dt * rate );
126     if (Tanks[i]->GetType() == FGTank::ttFUEL) {
127       TotalFuelQuantity += Tanks[i]->GetContents();
128     }
129   }
130
131   if (refuel) DoRefuel( dt * rate );
132
133   return false;
134 }
135
136 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137
138 bool FGPropulsion::GetSteadyState(void)
139 {
140   double currentThrust = 0, lastThrust=-1;
141   int steady_count,j=0;
142   bool steady=false;
143
144   vForces.InitMatrix();
145   vMoments.InitMatrix();
146
147   if (!FGModel::Run()) {
148     for (unsigned int i=0; i<numEngines; i++) {
149       Engines[i]->SetTrimMode(true);
150       steady=false;
151       steady_count=0;
152       while (!steady && j < 6000) {
153         Engines[i]->Calculate();
154         lastThrust = currentThrust;
155         currentThrust = Engines[i]->GetThrust();
156         if (fabs(lastThrust-currentThrust) < 0.0001) {
157           steady_count++;
158           if (steady_count > 120) { steady=true; }
159         } else {
160           steady_count=0;
161         }
162         j++;
163       }
164       vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
165       vMoments += Engines[i]->GetMoments();     // sum body frame moments
166       Engines[i]->SetTrimMode(false);
167     }
168
169     return false;
170   } else {
171     return true;
172   }
173 }
174
175 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176
177 bool FGPropulsion::ICEngineStart(void)
178 {
179   int j;
180
181   vForces.InitMatrix();
182   vMoments.InitMatrix();
183
184   for (unsigned int i=0; i<numEngines; i++) {
185     Engines[i]->SetTrimMode(true);
186     j=0;
187     while (!Engines[i]->GetRunning() && j < 2000) {
188       Engines[i]->Calculate();
189       j++;
190     }
191     vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
192     vMoments += Engines[i]->GetMoments();     // sum body frame moments
193     Engines[i]->SetTrimMode(false);
194   }
195   return true;
196 }
197
198 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199
200 bool FGPropulsion::Load(Element* el)
201 {
202   string type, engine_filename;
203   bool ThrottleAdded = false;
204
205   Debug(2);
206
207   Element* engine_element = el->FindElement("engine");
208   while (engine_element) {
209     engine_filename = engine_element->GetAttributeValue("file");
210
211     if (engine_filename.empty()) {
212       cerr << "Engine definition did not supply an engine file." << endl;
213       return false;
214     }
215
216     engine_filename = FindEngineFullPathname(engine_filename);
217     document = LoadXMLDocument(engine_filename);
218     document->SetParent(engine_element);
219
220     type = document->GetName();
221     if (type == "piston_engine") {
222       HavePistonEngine = true;
223       if (!IsBound) bind();
224       Engines.push_back(new FGPiston(FDMExec, document, numEngines));
225     } else if (type == "turbine_engine") {
226       HaveTurbineEngine = true;
227       if (!IsBound) bind();
228       Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
229     } else if (type == "turboprop_engine") {
230       HaveTurboPropEngine = true;
231       if (!IsBound) bind();
232       Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
233     } else if (type == "rocket_engine") {
234       HaveRocketEngine = true;
235       if (!IsBound) bind();
236       Engines.push_back(new FGRocket(FDMExec, document, numEngines));
237     } else if (type == "electric_engine") {
238       HaveElectricEngine = true;
239       if (!IsBound) bind();
240       Engines.push_back(new FGElectric(FDMExec, document, numEngines));
241     } else {
242       cerr << "Unknown engine type: " << type << endl;
243       exit(-5);
244     }
245
246     FCS->AddThrottle();
247     ThrottleAdded = true;
248
249     numEngines++;
250
251     engine_element = el->FindNextElement("engine");
252     ResetParser();
253   }
254
255   // Process tank definitions
256
257   Element* tank_element = el->FindElement("tank");
258   while (tank_element) {
259     Tanks.push_back(new FGTank(FDMExec, tank_element));
260     if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
261     else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
262     else {cerr << "Unknown tank type specified." << endl; return false;}
263     numTanks++;
264     tank_element = el->FindNextElement("tank");
265   }
266   numSelectedFuelTanks = numFuelTanks;
267   numSelectedOxiTanks  = numOxiTanks;
268
269   CalculateTankInertias();
270   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
271
272   return true;
273 }
274
275 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276
277 string FGPropulsion::FindEngineFullPathname(string engine_filename)
278 {
279   string fullpath, localpath;
280   string enginePath = FDMExec->GetEnginePath();
281   string aircraftPath = FDMExec->GetFullAircraftPath();
282   ifstream* engine_file = new ifstream();
283
284   string separator = "/";
285 # ifdef macintosh
286   separator = ";";
287 # endif
288
289   fullpath = enginePath + separator;
290   localpath = aircraftPath + separator + "Engines" + separator;
291
292   engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
293   if ( !engine_file->is_open()) {
294     engine_file->open(string(localpath + engine_filename + ".xml").c_str());
295       if ( !engine_file->is_open()) {
296         cerr << " Could not open engine file: " << engine_filename << " in path "
297              << fullpath << " or " << localpath << endl;
298         return string("");
299       } else {
300         return string(localpath + engine_filename + ".xml");
301       }
302   }
303   return string(fullpath + engine_filename + ".xml");
304 }
305
306 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307
308 ifstream* FGPropulsion::FindEngineFile(string engine_filename)
309 {
310   string fullpath, localpath;
311   string enginePath = FDMExec->GetEnginePath();
312   string aircraftPath = FDMExec->GetFullAircraftPath();
313   ifstream* engine_file = new ifstream();
314
315   string separator = "/";
316 # ifdef macintosh
317   separator = ";";
318 # endif
319
320   fullpath = enginePath + separator;
321   localpath = aircraftPath + separator + "Engines" + separator;
322
323   engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
324   if ( !engine_file->is_open()) {
325     engine_file->open(string(localpath + engine_filename + ".xml").c_str());
326       if ( !engine_file->is_open()) {
327         cerr << " Could not open engine file: " << engine_filename << " in path "
328              << fullpath << " or " << localpath << endl;
329       }
330   }
331   return engine_file;
332 }
333
334 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335
336 string FGPropulsion::GetPropulsionStrings(string delimeter)
337 {
338   unsigned int i;
339
340   string PropulsionStrings = "";
341   bool firstime = true;
342   stringstream buf;
343
344   for (i=0; i<Engines.size(); i++) {
345     if (firstime)  firstime = false;
346     else           PropulsionStrings += delimeter;
347
348     PropulsionStrings += Engines[i]->GetEngineLabels(delimeter);
349   }
350   for (i=0; i<Tanks.size(); i++) {
351     if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i;
352     else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i;
353   }
354
355   return PropulsionStrings;
356 }
357
358 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359
360 string FGPropulsion::GetPropulsionValues(string delimeter)
361 {
362   unsigned int i;
363
364   string PropulsionValues = "";
365   bool firstime = true;
366   stringstream buf;
367
368   for (i=0; i<Engines.size(); i++) {
369     if (firstime)  firstime = false;
370     else           PropulsionValues += delimeter;
371
372     PropulsionValues += Engines[i]->GetEngineValues(delimeter);
373   }
374   for (i=0; i<Tanks.size(); i++) {
375     buf << delimeter;
376     buf << Tanks[i]->GetContents();
377   }
378
379   return PropulsionValues;
380 }
381
382 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383
384 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
385 {
386   iTank = Tanks.begin();
387   vXYZtank_arm.InitMatrix();
388   while (iTank < Tanks.end()) {
389     vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
390     vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
391     vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
392     iTank++;
393   }
394   return vXYZtank_arm;
395 }
396
397 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398
399 double FGPropulsion::GetTanksWeight(void)
400 {
401   double Tw = 0.0;
402
403   iTank = Tanks.begin();
404   while (iTank < Tanks.end()) {
405     Tw += (*iTank)->GetContents();
406     iTank++;
407   }
408   return Tw;
409 }
410
411 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
412
413 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
414 {
415   unsigned int size;
416
417   size = Tanks.size();
418   if (size == 0) return tankJ;
419
420   tankJ = FGMatrix33();
421
422   for (unsigned int i=0; i<size; i++)
423     tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
424                                                Tanks[i]->GetXYZ() );
425
426   return tankJ;
427 }
428
429 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430
431 void FGPropulsion::SetMagnetos(int setting)
432 {
433   if (ActiveEngine < 0) {
434     for (unsigned i=0; i<Engines.size(); i++) {
435       // ToDo: first need to make sure the engine Type is really appropriate:
436       //   do a check to see if it is of type Piston. This should be done for
437       //   all of this kind of possibly across-the-board settings.
438       ((FGPiston*)Engines[i])->SetMagnetos(setting);
439     }
440   } else {
441     ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
442   }
443 }
444
445 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446
447 void FGPropulsion::SetStarter(int setting)
448 {
449   if (ActiveEngine < 0) {
450     for (unsigned i=0; i<Engines.size(); i++) {
451       if (setting == 0)
452         Engines[i]->SetStarter(false);
453       else
454         Engines[i]->SetStarter(true);
455     }
456   } else {
457     if (setting == 0)
458       Engines[ActiveEngine]->SetStarter(false);
459     else
460       Engines[ActiveEngine]->SetStarter(true);
461   }
462 }
463
464 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465
466 void FGPropulsion::SetCutoff(int setting)
467 {
468   if (ActiveEngine < 0) {
469     for (unsigned i=0; i<Engines.size(); i++) {
470       if (setting == 0)
471         ((FGTurbine*)Engines[i])->SetCutoff(false);
472       else
473         ((FGTurbine*)Engines[i])->SetCutoff(true);
474     }
475   } else {
476     if (setting == 0)
477       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
478     else
479       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
480   }
481 }
482
483 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484
485 void FGPropulsion::SetActiveEngine(int engine)
486 {
487   if (engine >= (int)Engines.size() || engine < 0)
488     ActiveEngine = -1;
489   else
490     ActiveEngine = engine;
491 }
492
493 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494
495 double FGPropulsion::Transfer(int source, int target, double amount)
496 {
497  double shortage, overage;
498
499   if (source == -1) {
500      shortage = 0.0;
501   } else {
502      shortage = Tanks[source]->Drain(amount);
503   }
504   if (target == -1) {
505      overage = 0.0;
506   } else {
507      overage = Tanks[target]->Fill(amount - shortage);
508   }
509   return overage;
510 }
511
512 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513
514 void FGPropulsion::DoRefuel(double time_slice)
515 {
516   unsigned int i;
517
518   double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
519   int TanksNotFull = 0;
520
521   for (i=0; i<numTanks; i++) {
522     if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
523   }
524
525   if (TanksNotFull) {
526     for (i=0; i<numTanks; i++) {
527       if (Tanks[i]->GetPctFull() < 99.99)
528           Transfer(-1, i, fillrate/TanksNotFull);
529     }
530   }
531 }
532
533 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534
535 void FGPropulsion::SetFuelFreeze(bool f)
536 {
537   fuel_freeze = f;
538   for (unsigned int i=0; i<numEngines; i++) {
539     Engines[i]->SetFuelFreeze(f);
540   }
541 }
542
543 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544
545 void FGPropulsion::bind(void)
546 {
547   typedef double (FGPropulsion::*PMF)(int) const;
548   typedef int (FGPropulsion::*iPMF)(void) const;
549
550   IsBound = true;
551
552   if (HaveTurbineEngine) {
553     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
554     PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   true);
555   }
556
557   if (HavePistonEngine) {
558     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
559     PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
560   }
561
562   PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
563                         &FGPropulsion::SetActiveEngine, true);
564   PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
565 }
566
567 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
568
569 void FGPropulsion::unbind(void)
570 {
571   if (!IsBound) return;
572
573   if (HaveTurbineEngine) {
574     PropertyManager->Untie("propulsion/starter_cmd");
575     PropertyManager->Untie("propulsion/cutoff_cmd");
576   }
577   if (HavePistonEngine) {
578     PropertyManager->Untie("propulsion/starter_cmd");
579     PropertyManager->Untie("propulsion/magneto_cmd");
580   }
581   PropertyManager->Untie("propulsion/active_engine");
582   PropertyManager->Untie("propulsion/total-fuel-lbs");
583 }
584
585 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 //    The bitmasked value choices are as follows:
587 //    unset: In this case (the default) JSBSim would only print
588 //       out the normally expected messages, essentially echoing
589 //       the config files as they are read. If the environment
590 //       variable is not set, debug_lvl is set to 1 internally
591 //    0: This requests JSBSim not to output any messages
592 //       whatsoever.
593 //    1: This value explicity requests the normal JSBSim
594 //       startup messages
595 //    2: This value asks for a message to be printed out when
596 //       a class is instantiated
597 //    4: When this value is set, a message is displayed when a
598 //       FGModel object executes its Run() method
599 //    8: When this value is set, various runtime state variables
600 //       are printed out periodically
601 //    16: When set various parameters are sanity checked and
602 //       a message is printed out when they go out of bounds
603
604 void FGPropulsion::Debug(int from)
605 {
606   if (debug_lvl <= 0) return;
607
608   if (debug_lvl & 1) { // Standard console startup message output
609     if (from == 2) { // Loader
610       cout << endl << "  Propulsion:" << endl;
611     }
612   }
613   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
614     if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
615     if (from == 1) cout << "Destroyed:    FGPropulsion" << endl;
616   }
617   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
618   }
619   if (debug_lvl & 8 ) { // Runtime state variables
620   }
621   if (debug_lvl & 16) { // Sanity checking
622   }
623   if (debug_lvl & 64) {
624     if (from == 0) { // Constructor
625       cout << IdSrc << endl;
626       cout << IdHdr << endl;
627     }
628   }
629 }
630 }