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