]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/models/FGPropulsion.cpp
a6f45021fb8a3d2972cc66a5ee9ef389dff78fa4
[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   bool ThrottleAdded = false;
203
204   Debug(2);
205
206   Element* engine_element = el->FindElement("engine");
207   while (engine_element) {
208     engine_filename = engine_element->GetAttributeValue("file");
209
210     if (engine_filename.empty()) {
211       cerr << "Engine definition did not supply an engine file." << endl;
212       return false;
213     }
214
215     engine_filename = FindEngineFullPathname(engine_filename);
216     document = LoadXMLDocument(engine_filename);
217     document->SetParent(engine_element);
218
219     type = document->GetName();
220     if (type == "piston_engine") {
221       HavePistonEngine = true;
222       if (!IsBound) bind();
223       Engines.push_back(new FGPiston(FDMExec, document, numEngines));
224     } else if (type == "turbine_engine") {
225       HaveTurbineEngine = true;
226       if (!IsBound) bind();
227       Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
228     } else if (type == "turboprop_engine") {
229       HaveTurboPropEngine = true;
230       if (!IsBound) bind();
231       Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
232     } else if (type == "rocket_engine") {
233       HaveRocketEngine = true;
234       if (!IsBound) bind();
235       Engines.push_back(new FGRocket(FDMExec, document, numEngines));
236     } else if (type == "electric_engine") {
237       HaveElectricEngine = true;
238       if (!IsBound) bind();
239       Engines.push_back(new FGElectric(FDMExec, document, numEngines));
240     } else {
241       cerr << "Unknown engine type: " << type << endl;
242       exit(-5);
243     }
244
245     FCS->AddThrottle();
246     ThrottleAdded = true;
247
248     numEngines++;
249
250     engine_element = el->FindNextElement("engine");
251     ResetParser();
252   }
253
254   // Process tank definitions
255
256   Element* tank_element = el->FindElement("tank");
257   while (tank_element) {
258     Tanks.push_back(new FGTank(FDMExec, tank_element));
259     if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
260     else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
261     else {cerr << "Unknown tank type specified." << endl; return false;}
262     numTanks++;
263     tank_element = el->FindNextElement("tank");
264   }
265   numSelectedFuelTanks = numFuelTanks;
266   numSelectedOxiTanks  = numOxiTanks;
267
268   CalculateTankInertias();
269   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
270
271   return true;
272 }
273
274 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275
276 string FGPropulsion::FindEngineFullPathname(string engine_filename)
277 {
278   string fullpath, localpath;
279   string enginePath = FDMExec->GetEnginePath();
280   string aircraftPath = FDMExec->GetFullAircraftPath();
281   ifstream* engine_file = new ifstream();
282
283   string separator = "/";
284 # ifdef macintosh
285   separator = ";";
286 # endif
287
288   fullpath = enginePath + separator;
289   localpath = aircraftPath + separator + "Engines" + separator;
290
291   engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
292   if ( !engine_file->is_open()) {
293     engine_file->open(string(localpath + engine_filename + ".xml").c_str());
294       if ( !engine_file->is_open()) {
295         cerr << " Could not open engine file: " << engine_filename << " in path "
296              << fullpath << " or " << localpath << endl;
297         return string("");
298       } else {
299         return string(localpath + engine_filename + ".xml");
300       }
301   }
302   return string(fullpath + engine_filename + ".xml");
303 }
304
305 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306
307 ifstream* FGPropulsion::FindEngineFile(string engine_filename)
308 {
309   string fullpath, localpath;
310   string enginePath = FDMExec->GetEnginePath();
311   string aircraftPath = FDMExec->GetFullAircraftPath();
312   ifstream* engine_file = new ifstream();
313
314   string separator = "/";
315 # ifdef macintosh
316   separator = ";";
317 # endif
318
319   fullpath = enginePath + separator;
320   localpath = aircraftPath + separator + "Engines" + separator;
321
322   engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
323   if ( !engine_file->is_open()) {
324     engine_file->open(string(localpath + engine_filename + ".xml").c_str());
325       if ( !engine_file->is_open()) {
326         cerr << " Could not open engine file: " << engine_filename << " in path "
327              << fullpath << " or " << localpath << endl;
328       }
329   }
330   return engine_file;
331 }
332
333 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334
335 string FGPropulsion::GetPropulsionStrings(string delimeter)
336 {
337   unsigned int i;
338
339   string PropulsionStrings = "";
340   bool firstime = true;
341   stringstream buf;
342
343   for (i=0; i<Engines.size(); i++) {
344     if (firstime)  firstime = false;
345     else           PropulsionStrings += delimeter;
346
347     PropulsionStrings += Engines[i]->GetEngineLabels(delimeter);
348   }
349   for (i=0; i<Tanks.size(); i++) {
350     if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i;
351     else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i;
352   }
353
354   return PropulsionStrings;
355 }
356
357 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358
359 string FGPropulsion::GetPropulsionValues(string delimeter)
360 {
361   unsigned int i;
362
363   string PropulsionValues = "";
364   bool firstime = true;
365   stringstream buf;
366
367   for (i=0; i<Engines.size(); i++) {
368     if (firstime)  firstime = false;
369     else           PropulsionValues += delimeter;
370
371     PropulsionValues += Engines[i]->GetEngineValues(delimeter);
372   }
373   for (i=0; i<Tanks.size(); i++) {
374     buf << delimeter;
375     buf << Tanks[i]->GetContents();
376   }
377
378   return PropulsionValues;
379 }
380
381 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382
383 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
384 {
385   iTank = Tanks.begin();
386   vXYZtank_arm.InitMatrix();
387   while (iTank < Tanks.end()) {
388     vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
389     vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
390     vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
391     iTank++;
392   }
393   return vXYZtank_arm;
394 }
395
396 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397
398 double FGPropulsion::GetTanksWeight(void)
399 {
400   double Tw = 0.0;
401
402   iTank = Tanks.begin();
403   while (iTank < Tanks.end()) {
404     Tw += (*iTank)->GetContents();
405     iTank++;
406   }
407   return Tw;
408 }
409
410 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411
412 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
413 {
414   unsigned int size;
415
416   size = Tanks.size();
417   if (size == 0) return tankJ;
418
419   tankJ = FGMatrix33();
420
421   for (unsigned int i=0; i<size; i++)
422     tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
423                                                Tanks[i]->GetXYZ() );
424
425   return tankJ;
426 }
427
428 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429
430 void FGPropulsion::SetMagnetos(int setting)
431 {
432   if (ActiveEngine < 0) {
433     for (unsigned i=0; i<Engines.size(); i++) {
434       // ToDo: first need to make sure the engine Type is really appropriate:
435       //   do a check to see if it is of type Piston. This should be done for
436       //   all of this kind of possibly across-the-board settings.
437       ((FGPiston*)Engines[i])->SetMagnetos(setting);
438     }
439   } else {
440     ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
441   }
442 }
443
444 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445
446 void FGPropulsion::SetStarter(int setting)
447 {
448   if (ActiveEngine < 0) {
449     for (unsigned i=0; i<Engines.size(); i++) {
450       if (setting == 0)
451         Engines[i]->SetStarter(false);
452       else
453         Engines[i]->SetStarter(true);
454     }
455   } else {
456     if (setting == 0)
457       Engines[ActiveEngine]->SetStarter(false);
458     else
459       Engines[ActiveEngine]->SetStarter(true);
460   }
461 }
462
463 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464
465 void FGPropulsion::SetCutoff(int setting)
466 {
467   if (ActiveEngine < 0) {
468     for (unsigned i=0; i<Engines.size(); i++) {
469       if (setting == 0)
470         ((FGTurbine*)Engines[i])->SetCutoff(false);
471       else
472         ((FGTurbine*)Engines[i])->SetCutoff(true);
473     }
474   } else {
475     if (setting == 0)
476       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
477     else
478       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
479   }
480 }
481
482 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483
484 void FGPropulsion::SetActiveEngine(int engine)
485 {
486   if (engine >= (int)Engines.size() || engine < 0)
487     ActiveEngine = -1;
488   else
489     ActiveEngine = engine;
490 }
491
492 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493
494 double FGPropulsion::Transfer(int source, int target, double amount)
495 {
496  double shortage, overage;
497
498   if (source == -1) {
499      shortage = 0.0;
500   } else {
501      shortage = Tanks[source]->Drain(amount);
502   }
503   if (target == -1) {
504      overage = 0.0;
505   } else {
506      overage = Tanks[target]->Fill(amount - shortage);
507   }
508   return overage;
509 }
510
511 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512
513 void FGPropulsion::DoRefuel(double time_slice)
514 {
515   unsigned int i;
516
517   double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
518   int TanksNotFull = 0;
519
520   for (i=0; i<numTanks; i++) {
521     if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
522   }
523
524   if (TanksNotFull) {
525     for (i=0; i<numTanks; i++) {
526       if (Tanks[i]->GetPctFull() < 99.99)
527           Transfer(-1, i, fillrate/TanksNotFull);
528     }
529   }
530 }
531
532 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533
534 void FGPropulsion::SetFuelFreeze(bool f)
535 {
536   fuel_freeze = f;
537   for (unsigned int i=0; i<numEngines; i++) {
538     Engines[i]->SetFuelFreeze(f);
539   }
540 }
541
542 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543
544 void FGPropulsion::bind(void)
545 {
546   typedef double (FGPropulsion::*PMF)(int) const;
547   typedef int (FGPropulsion::*iPMF)(void) const;
548
549   IsBound = true;
550
551   if (HaveTurbineEngine) {
552     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
553     PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   true);
554   }
555
556   if (HavePistonEngine) {
557     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
558     PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
559   }
560
561   PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
562                         &FGPropulsion::SetActiveEngine, true);
563   PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
564 }
565
566 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567
568 void FGPropulsion::unbind(void)
569 {
570   if (!IsBound) return;
571
572   if (HaveTurbineEngine) {
573     PropertyManager->Untie("propulsion/starter_cmd");
574     PropertyManager->Untie("propulsion/cutoff_cmd");
575   }
576   if (HavePistonEngine) {
577     PropertyManager->Untie("propulsion/starter_cmd");
578     PropertyManager->Untie("propulsion/magneto_cmd");
579   }
580   PropertyManager->Untie("propulsion/active_engine");
581   PropertyManager->Untie("propulsion/total-fuel-lbs");
582 }
583
584 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585 //    The bitmasked value choices are as follows:
586 //    unset: In this case (the default) JSBSim would only print
587 //       out the normally expected messages, essentially echoing
588 //       the config files as they are read. If the environment
589 //       variable is not set, debug_lvl is set to 1 internally
590 //    0: This requests JSBSim not to output any messages
591 //       whatsoever.
592 //    1: This value explicity requests the normal JSBSim
593 //       startup messages
594 //    2: This value asks for a message to be printed out when
595 //       a class is instantiated
596 //    4: When this value is set, a message is displayed when a
597 //       FGModel object executes its Run() method
598 //    8: When this value is set, various runtime state variables
599 //       are printed out periodically
600 //    16: When set various parameters are sanity checked and
601 //       a message is printed out when they go out of bounds
602
603 void FGPropulsion::Debug(int from)
604 {
605   if (debug_lvl <= 0) return;
606
607   if (debug_lvl & 1) { // Standard console startup message output
608     if (from == 2) { // Loader
609       cout << endl << "  Propulsion:" << endl;
610     }
611   }
612   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
613     if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
614     if (from == 1) cout << "Destroyed:    FGPropulsion" << endl;
615   }
616   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
617   }
618   if (debug_lvl & 8 ) { // Runtime state variables
619   }
620   if (debug_lvl & 16) { // Sanity checking
621   }
622   if (debug_lvl & 64) {
623     if (from == 0) { // Constructor
624       cout << IdSrc << endl;
625       cout << IdHdr << endl;
626     }
627   }
628 }
629 }