1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGPropulsion.cpp
6 Purpose: Encapsulates the set of engines and tanks associated
9 ------------- Copyright (C) 2000 Jon S. Berndt (jon@jsbsim.org) -------------
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
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
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.
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.
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:
34 1) The appropriate engine type instance is created
35 2) At least one tank object is created, and is linked to an engine.
37 At Run time each engines Calculate() method is called.
40 --------------------------------------------------------------------------------
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47 #include "FGPropulsion.h"
48 #include "models/FGFCS.h"
49 #include "models/FGMassBalance.h"
50 #include "models/propulsion/FGThruster.h"
51 #include "models/propulsion/FGRocket.h"
52 #include "models/propulsion/FGTurbine.h"
53 #include "models/propulsion/FGPiston.h"
54 #include "models/propulsion/FGElectric.h"
55 #include "models/propulsion/FGTurboProp.h"
56 #include "models/propulsion/FGTank.h"
57 #include "input_output/FGPropertyManager.h"
58 #include "input_output/FGXMLParse.h"
59 #include "math/FGColumnVector3.h"
68 static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.43 2010/11/18 12:38:06 jberndt Exp $";
69 static const char *IdHdr = ID_PROPULSION;
71 extern short debug_lvl;
74 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
78 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
80 Name = "FGPropulsion";
82 InitializedEngines = 0;
83 numSelectedFuelTanks = numSelectedOxiTanks = 0;
84 numTanks = numEngines = 0;
85 numOxiTanks = numFuelTanks = 0;
86 ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
88 refuel = dump = false;
91 TotalFuelQuantity = 0.0;
97 HaveElectricEngine = false;
98 HasInitializedEngines = false;
103 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105 FGPropulsion::~FGPropulsion()
107 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
109 for (unsigned int i=0; i<Tanks.size(); i++) delete Tanks[i];
114 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 bool FGPropulsion::InitModel(void)
120 if (!FGModel::InitModel()) return false;
122 for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
124 for (unsigned int i=0; i<numEngines; i++) {
125 switch (Engines[i]->GetType()) {
126 case FGEngine::etPiston:
127 ((FGPiston*)Engines[i])->ResetToIC();
129 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
130 } catch (string str) {
135 case FGEngine::etTurbine:
136 ((FGTurbine*)Engines[i])->ResetToIC();
138 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
139 } catch (string str) {
152 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 bool FGPropulsion::Run(void)
158 if (FGModel::Run()) return true;
159 if (FDMExec->Holding()) return false;
163 double dt = FDMExec->GetDeltaT();
165 vForces.InitMatrix();
166 vMoments.InitMatrix();
168 for (i=0; i<numEngines; i++) {
169 Engines[i]->Calculate();
170 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
171 vMoments += Engines[i]->GetMoments(); // sum body frame moments
174 TotalFuelQuantity = 0.0;
175 for (i=0; i<numTanks; i++) {
176 Tanks[i]->Calculate( dt * rate );
177 if (Tanks[i]->GetType() == FGTank::ttFUEL) {
178 TotalFuelQuantity += Tanks[i]->GetContents();
182 if (refuel) DoRefuel( dt * rate );
183 if (dump) DumpFuel( dt * rate );
190 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 bool FGPropulsion::GetSteadyState(void)
194 double currentThrust = 0, lastThrust = -1;
195 int steady_count = 0, j = 0;
198 vForces.InitMatrix();
199 vMoments.InitMatrix();
201 if (!FGModel::Run()) {
202 for (unsigned int i=0; i<numEngines; i++) {
203 // cout << " Finding steady state for engine " << i << endl;
204 Engines[i]->SetTrimMode(true);
208 while (!steady && j < 6000) {
209 Engines[i]->Calculate();
210 lastThrust = currentThrust;
211 currentThrust = Engines[i]->GetThruster()->GetThrust();
212 if (fabs(lastThrust-currentThrust) < 0.0001) {
214 if (steady_count > 120) {
216 // cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl;
224 // cout << " Could not find a steady state for this engine." << endl;
226 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
227 vMoments += Engines[i]->GetMoments(); // sum body frame moments
228 Engines[i]->SetTrimMode(false);
237 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 void FGPropulsion::InitRunning(int n)
241 if (n >= 0) { // A specific engine is supposed to be initialized
243 if (n >= (int)GetNumEngines() ) {
244 throw(string("Tried to initialize a non-existent engine!"));
246 FDMExec->GetFCS()->SetThrottleCmd(n,1);
247 FDMExec->GetFCS()->SetMixtureCmd(n,1);
248 GetEngine(n)->InitRunning();
251 InitializedEngines = 1 << n;
252 HasInitializedEngines = true;
254 } else if (n < 0) { // -1 refers to "All Engines"
256 for (unsigned int i=0; i<GetNumEngines(); i++) {
257 FDMExec->GetFCS()->SetThrottleCmd(i,1);
258 FDMExec->GetFCS()->SetMixtureCmd(i,1);
259 GetEngine(i)->InitRunning();
262 InitializedEngines = -1;
263 HasInitializedEngines = true;
268 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270 bool FGPropulsion::Load(Element* el)
272 string type, engine_filename;
273 bool ThrottleAdded = false;
277 FGModel::Load(el); // Perform base class Load.
279 // Process tank definitions first to establish the number of fuel tanks
281 Element* tank_element = el->FindElement("tank");
282 while (tank_element) {
283 Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
284 if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
285 else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
286 else {cerr << "Unknown tank type specified." << endl; return false;}
288 tank_element = el->FindNextElement("tank");
290 numSelectedFuelTanks = numFuelTanks;
291 numSelectedOxiTanks = numOxiTanks;
293 Element* engine_element = el->FindElement("engine");
294 while (engine_element) {
295 engine_filename = engine_element->GetAttributeValue("file");
297 if (engine_filename.empty()) {
298 cerr << "Engine definition did not supply an engine file." << endl;
302 engine_filename = FindEngineFullPathname(engine_filename);
303 document = LoadXMLDocument(engine_filename);
304 document->SetParent(engine_element);
306 type = document->GetName();
308 if (type == "piston_engine") {
309 HavePistonEngine = true;
310 if (!IsBound) bind();
311 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
312 } else if (type == "turbine_engine") {
313 HaveTurbineEngine = true;
314 if (!IsBound) bind();
315 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
316 } else if (type == "turboprop_engine") {
317 HaveTurboPropEngine = true;
318 if (!IsBound) bind();
319 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
320 } else if (type == "rocket_engine") {
321 HaveRocketEngine = true;
322 if (!IsBound) bind();
323 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
324 } else if (type == "electric_engine") {
325 HaveElectricEngine = true;
326 if (!IsBound) bind();
327 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
329 cerr << "Unknown engine type: " << type << endl;
332 } catch (std::string str) {
333 cerr << endl << fgred << str << reset << endl;
337 FDMExec->GetFCS()->AddThrottle();
338 ThrottleAdded = true;
342 engine_element = el->FindNextElement("engine");
346 CalculateTankInertias();
347 if (!ThrottleAdded) FDMExec->GetFCS()->AddThrottle(); // need to have at least one throttle
349 // Process fuel dump rate
350 if (el->FindElement("dump-rate"))
351 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
353 PostLoad(el, PropertyManager);
358 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360 string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
362 string fullpath, localpath;
363 string enginePath = FDMExec->GetEnginePath();
364 string aircraftPath = FDMExec->GetFullAircraftPath();
365 ifstream engine_file;
367 string separator = "/";
369 fullpath = enginePath + separator;
370 localpath = aircraftPath + separator + "Engines" + separator;
372 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
373 if ( !engine_file.is_open()) {
374 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
375 if ( !engine_file.is_open()) {
376 cerr << " Could not open engine file: " << engine_filename << " in path "
377 << fullpath << " or " << localpath << endl;
380 return string(localpath + engine_filename + ".xml");
383 return string(fullpath + engine_filename + ".xml");
386 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388 ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
390 string fullpath, localpath;
391 string enginePath = FDMExec->GetEnginePath();
392 string aircraftPath = FDMExec->GetFullAircraftPath();
393 ifstream* engine_file = new ifstream();
395 string separator = "/";
397 fullpath = enginePath + separator;
398 localpath = aircraftPath + separator + "Engines" + separator;
400 engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
401 if ( !engine_file->is_open()) {
402 engine_file->open(string(localpath + engine_filename + ".xml").c_str());
403 if ( !engine_file->is_open()) {
404 cerr << " Could not open engine file: " << engine_filename << " in path "
405 << fullpath << " or " << localpath << endl;
411 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413 string FGPropulsion::GetPropulsionStrings(const string& delimiter) const
417 string PropulsionStrings = "";
418 bool firstime = true;
421 for (i=0; i<Engines.size(); i++) {
422 if (firstime) firstime = false;
423 else PropulsionStrings += delimiter;
425 PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
427 for (i=0; i<Tanks.size(); i++) {
428 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
429 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
432 return PropulsionStrings;
435 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 string FGPropulsion::GetPropulsionValues(const string& delimiter) const
441 string PropulsionValues = "";
442 bool firstime = true;
445 for (i=0; i<Engines.size(); i++) {
446 if (firstime) firstime = false;
447 else PropulsionValues += delimiter;
449 PropulsionValues += Engines[i]->GetEngineValues(delimiter);
451 for (i=0; i<Tanks.size(); i++) {
453 buf << Tanks[i]->GetContents();
456 return PropulsionValues;
459 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
463 vXYZtank_arm.InitMatrix();
464 for (unsigned int i=0; i<Tanks.size(); i++) {
465 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
466 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
467 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
472 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474 double FGPropulsion::GetTanksWeight(void)
478 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
483 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
490 if (size == 0) return tankJ;
492 tankJ = FGMatrix33();
494 for (unsigned int i=0; i<size; i++) {
495 tankJ += FDMExec->GetMassBalance()->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
496 Tanks[i]->GetXYZ() );
497 tankJ(1,1) += Tanks[i]->GetIxx();
498 tankJ(2,2) += Tanks[i]->GetIyy();
499 tankJ(3,3) += Tanks[i]->GetIzz();
505 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 void FGPropulsion::SetMagnetos(int setting)
509 if (ActiveEngine < 0) {
510 for (unsigned i=0; i<Engines.size(); i++) {
511 // ToDo: first need to make sure the engine Type is really appropriate:
512 // do a check to see if it is of type Piston. This should be done for
513 // all of this kind of possibly across-the-board settings.
514 ((FGPiston*)Engines[i])->SetMagnetos(setting);
517 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
521 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
523 void FGPropulsion::SetStarter(int setting)
525 if (ActiveEngine < 0) {
526 for (unsigned i=0; i<Engines.size(); i++) {
528 Engines[i]->SetStarter(false);
530 Engines[i]->SetStarter(true);
534 Engines[ActiveEngine]->SetStarter(false);
536 Engines[ActiveEngine]->SetStarter(true);
540 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542 void FGPropulsion::SetCutoff(int setting)
544 if (ActiveEngine < 0) {
545 for (unsigned i=0; i<Engines.size(); i++) {
547 ((FGTurbine*)Engines[i])->SetCutoff(false);
549 ((FGTurbine*)Engines[i])->SetCutoff(true);
553 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
555 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
559 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 void FGPropulsion::SetActiveEngine(int engine)
563 if (engine >= (int)Engines.size() || engine < 0)
566 ActiveEngine = engine;
569 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 double FGPropulsion::Transfer(int source, int target, double amount)
573 double shortage, overage;
578 shortage = Tanks[source]->Drain(amount);
583 overage = Tanks[target]->Fill(amount - shortage);
588 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590 void FGPropulsion::DoRefuel(double time_slice)
594 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
595 int TanksNotFull = 0;
597 for (i=0; i<numTanks; i++) {
598 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
602 for (i=0; i<numTanks; i++) {
603 if (Tanks[i]->GetPctFull() < 99.99)
604 Transfer(-1, i, fillrate/TanksNotFull);
609 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 void FGPropulsion::DumpFuel(double time_slice)
614 int TanksDumping = 0;
616 for (i=0; i<numTanks; i++) {
617 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
620 if (TanksDumping == 0) return;
622 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
624 for (i=0; i<numTanks; i++) {
625 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
626 Transfer(i, -1, dump_rate_per_tank);
631 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633 void FGPropulsion::SetFuelFreeze(bool f)
636 for (unsigned int i=0; i<numEngines; i++) {
637 Engines[i]->SetFuelFreeze(f);
641 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 void FGPropulsion::bind(void)
645 typedef double (FGPropulsion::*PMF)(int) const;
646 typedef int (FGPropulsion::*iPMF)(void) const;
649 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
650 if (HaveTurbineEngine) {
651 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
652 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
655 if (HavePistonEngine) {
656 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
657 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
660 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
661 &FGPropulsion::SetActiveEngine, true);
662 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
663 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
664 &FGPropulsion::SetRefuel, true);
665 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
666 &FGPropulsion::SetFuelDump, true);
667 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
668 (PMF)&FGPropulsion::GetForces);
669 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
670 (PMF)&FGPropulsion::GetForces);
671 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
672 (PMF)&FGPropulsion::GetForces);
673 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
674 (PMF)&FGPropulsion::GetMoments);
675 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
676 (PMF)&FGPropulsion::GetMoments);
677 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
678 (PMF)&FGPropulsion::GetMoments);
682 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 // The bitmasked value choices are as follows:
684 // unset: In this case (the default) JSBSim would only print
685 // out the normally expected messages, essentially echoing
686 // the config files as they are read. If the environment
687 // variable is not set, debug_lvl is set to 1 internally
688 // 0: This requests JSBSim not to output any messages
690 // 1: This value explicity requests the normal JSBSim
692 // 2: This value asks for a message to be printed out when
693 // a class is instantiated
694 // 4: When this value is set, a message is displayed when a
695 // FGModel object executes its Run() method
696 // 8: When this value is set, various runtime state variables
697 // are printed out periodically
698 // 16: When set various parameters are sanity checked and
699 // a message is printed out when they go out of bounds
701 void FGPropulsion::Debug(int from)
703 if (debug_lvl <= 0) return;
705 if (debug_lvl & 1) { // Standard console startup message output
706 if (from == 2) { // Loader
707 cout << endl << " Propulsion:" << endl;
710 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
711 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
712 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
714 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
716 if (debug_lvl & 8 ) { // Runtime state variables
718 if (debug_lvl & 16) { // Sanity checking
720 if (debug_lvl & 64) {
721 if (from == 0) { // Constructor
722 cout << IdSrc << endl;
723 cout << IdHdr << endl;