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.45 2011/02/13 00:42:45 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;
197 bool TrimMode = FDMExec->GetTrimStatus();
199 vForces.InitMatrix();
200 vMoments.InitMatrix();
202 if (!FGModel::Run()) {
203 FDMExec->SetTrimStatus(true);
205 for (unsigned int i=0; i<numEngines; i++) {
206 // cout << " Finding steady state for engine " << i << endl;
210 while (!steady && j < 6000) {
211 Engines[i]->Calculate();
212 lastThrust = currentThrust;
213 currentThrust = Engines[i]->GetThruster()->GetThrust();
214 if (fabs(lastThrust-currentThrust) < 0.0001) {
216 if (steady_count > 120) {
218 // cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl;
226 // cout << " Could not find a steady state for this engine." << endl;
228 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
229 vMoments += Engines[i]->GetMoments(); // sum body frame moments
232 FDMExec->SetTrimStatus(TrimMode);
240 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 void FGPropulsion::InitRunning(int n)
244 if (n >= 0) { // A specific engine is supposed to be initialized
246 if (n >= (int)GetNumEngines() ) {
247 throw(string("Tried to initialize a non-existent engine!"));
249 FDMExec->GetFCS()->SetThrottleCmd(n,1);
250 FDMExec->GetFCS()->SetMixtureCmd(n,1);
251 GetEngine(n)->InitRunning();
254 InitializedEngines = 1 << n;
255 HasInitializedEngines = true;
257 } else if (n < 0) { // -1 refers to "All Engines"
259 for (unsigned int i=0; i<GetNumEngines(); i++) {
260 FDMExec->GetFCS()->SetThrottleCmd(i,1);
261 FDMExec->GetFCS()->SetMixtureCmd(i,1);
262 GetEngine(i)->InitRunning();
265 InitializedEngines = -1;
266 HasInitializedEngines = true;
271 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273 bool FGPropulsion::Load(Element* el)
275 string type, engine_filename;
276 bool ThrottleAdded = false;
280 FGModel::Load(el); // Perform base class Load.
282 // Process tank definitions first to establish the number of fuel tanks
284 Element* tank_element = el->FindElement("tank");
285 while (tank_element) {
286 Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
287 if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
288 else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
289 else {cerr << "Unknown tank type specified." << endl; return false;}
291 tank_element = el->FindNextElement("tank");
293 numSelectedFuelTanks = numFuelTanks;
294 numSelectedOxiTanks = numOxiTanks;
296 Element* engine_element = el->FindElement("engine");
297 while (engine_element) {
298 engine_filename = engine_element->GetAttributeValue("file");
300 if (engine_filename.empty()) {
301 cerr << "Engine definition did not supply an engine file." << endl;
305 engine_filename = FindEngineFullPathname(engine_filename);
306 document = LoadXMLDocument(engine_filename);
307 document->SetParent(engine_element);
309 type = document->GetName();
311 if (type == "piston_engine") {
312 HavePistonEngine = true;
313 if (!IsBound) bind();
314 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
315 } else if (type == "turbine_engine") {
316 HaveTurbineEngine = true;
317 if (!IsBound) bind();
318 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
319 } else if (type == "turboprop_engine") {
320 HaveTurboPropEngine = true;
321 if (!IsBound) bind();
322 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
323 } else if (type == "rocket_engine") {
324 HaveRocketEngine = true;
325 if (!IsBound) bind();
326 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
327 } else if (type == "electric_engine") {
328 HaveElectricEngine = true;
329 if (!IsBound) bind();
330 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
332 cerr << "Unknown engine type: " << type << endl;
335 } catch (std::string str) {
336 cerr << endl << fgred << str << reset << endl;
340 FDMExec->GetFCS()->AddThrottle();
341 ThrottleAdded = true;
345 engine_element = el->FindNextElement("engine");
349 CalculateTankInertias();
350 if (!ThrottleAdded) FDMExec->GetFCS()->AddThrottle(); // need to have at least one throttle
352 // Process fuel dump rate
353 if (el->FindElement("dump-rate"))
354 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
356 PostLoad(el, PropertyManager);
361 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
365 string fullpath, localpath;
366 string enginePath = FDMExec->GetEnginePath();
367 string aircraftPath = FDMExec->GetFullAircraftPath();
368 ifstream engine_file;
370 string separator = "/";
372 fullpath = enginePath + separator;
373 localpath = aircraftPath + separator + "Engines" + separator;
375 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
376 if ( !engine_file.is_open()) {
377 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
378 if ( !engine_file.is_open()) {
379 cerr << " Could not open engine file: " << engine_filename << " in path "
380 << fullpath << " or " << localpath << endl;
383 return string(localpath + engine_filename + ".xml");
386 return string(fullpath + engine_filename + ".xml");
389 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
393 string fullpath, localpath;
394 string enginePath = FDMExec->GetEnginePath();
395 string aircraftPath = FDMExec->GetFullAircraftPath();
396 ifstream* engine_file = new ifstream();
398 string separator = "/";
400 fullpath = enginePath + separator;
401 localpath = aircraftPath + separator + "Engines" + separator;
403 engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
404 if ( !engine_file->is_open()) {
405 engine_file->open(string(localpath + engine_filename + ".xml").c_str());
406 if ( !engine_file->is_open()) {
407 cerr << " Could not open engine file: " << engine_filename << " in path "
408 << fullpath << " or " << localpath << endl;
414 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 string FGPropulsion::GetPropulsionStrings(const string& delimiter) const
420 string PropulsionStrings = "";
421 bool firstime = true;
424 for (i=0; i<Engines.size(); i++) {
425 if (firstime) firstime = false;
426 else PropulsionStrings += delimiter;
428 PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
430 for (i=0; i<Tanks.size(); i++) {
431 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
432 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
435 return PropulsionStrings;
438 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 string FGPropulsion::GetPropulsionValues(const string& delimiter) const
444 string PropulsionValues = "";
445 bool firstime = true;
448 for (i=0; i<Engines.size(); i++) {
449 if (firstime) firstime = false;
450 else PropulsionValues += delimiter;
452 PropulsionValues += Engines[i]->GetEngineValues(delimiter);
454 for (i=0; i<Tanks.size(); i++) {
456 buf << Tanks[i]->GetContents();
459 return PropulsionValues;
462 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
466 vXYZtank_arm.InitMatrix();
467 for (unsigned int i=0; i<Tanks.size(); i++) {
468 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
469 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
470 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
475 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 double FGPropulsion::GetTanksWeight(void)
481 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
486 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
493 if (size == 0) return tankJ;
495 tankJ = FGMatrix33();
497 for (unsigned int i=0; i<size; i++) {
498 tankJ += FDMExec->GetMassBalance()->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
499 Tanks[i]->GetXYZ() );
500 tankJ(1,1) += Tanks[i]->GetIxx();
501 tankJ(2,2) += Tanks[i]->GetIyy();
502 tankJ(3,3) += Tanks[i]->GetIzz();
508 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 void FGPropulsion::SetMagnetos(int setting)
512 if (ActiveEngine < 0) {
513 for (unsigned i=0; i<Engines.size(); i++) {
514 // ToDo: first need to make sure the engine Type is really appropriate:
515 // do a check to see if it is of type Piston. This should be done for
516 // all of this kind of possibly across-the-board settings.
517 ((FGPiston*)Engines[i])->SetMagnetos(setting);
520 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
524 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 void FGPropulsion::SetStarter(int setting)
528 if (ActiveEngine < 0) {
529 for (unsigned i=0; i<Engines.size(); i++) {
531 Engines[i]->SetStarter(false);
533 Engines[i]->SetStarter(true);
537 Engines[ActiveEngine]->SetStarter(false);
539 Engines[ActiveEngine]->SetStarter(true);
543 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
545 void FGPropulsion::SetCutoff(int setting)
547 if (ActiveEngine < 0) {
548 for (unsigned i=0; i<Engines.size(); i++) {
550 ((FGTurbine*)Engines[i])->SetCutoff(false);
552 ((FGTurbine*)Engines[i])->SetCutoff(true);
556 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
558 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
562 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564 void FGPropulsion::SetActiveEngine(int engine)
566 if (engine >= (int)Engines.size() || engine < 0)
569 ActiveEngine = engine;
572 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 double FGPropulsion::Transfer(int source, int target, double amount)
576 double shortage, overage;
581 shortage = Tanks[source]->Drain(amount);
586 overage = Tanks[target]->Fill(amount - shortage);
591 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 void FGPropulsion::DoRefuel(double time_slice)
597 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
598 int TanksNotFull = 0;
600 for (i=0; i<numTanks; i++) {
601 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
605 for (i=0; i<numTanks; i++) {
606 if (Tanks[i]->GetPctFull() < 99.99)
607 Transfer(-1, i, fillrate/TanksNotFull);
612 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614 void FGPropulsion::DumpFuel(double time_slice)
617 int TanksDumping = 0;
619 for (i=0; i<numTanks; i++) {
620 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
623 if (TanksDumping == 0) return;
625 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
627 for (i=0; i<numTanks; i++) {
628 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
629 Transfer(i, -1, dump_rate_per_tank);
634 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
636 void FGPropulsion::SetFuelFreeze(bool f)
639 for (unsigned int i=0; i<numEngines; i++) {
640 Engines[i]->SetFuelFreeze(f);
644 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 void FGPropulsion::bind(void)
648 typedef double (FGPropulsion::*PMF)(int) const;
649 typedef int (FGPropulsion::*iPMF)(void) const;
652 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false);
653 if (HaveTurbineEngine) {
654 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false);
655 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, false);
658 if (HavePistonEngine) {
659 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false);
660 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, false);
663 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
664 &FGPropulsion::SetActiveEngine, true);
665 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
666 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
667 &FGPropulsion::SetRefuel, true);
668 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
669 &FGPropulsion::SetFuelDump, true);
670 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
671 (PMF)&FGPropulsion::GetForces);
672 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
673 (PMF)&FGPropulsion::GetForces);
674 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
675 (PMF)&FGPropulsion::GetForces);
676 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
677 (PMF)&FGPropulsion::GetMoments);
678 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
679 (PMF)&FGPropulsion::GetMoments);
680 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
681 (PMF)&FGPropulsion::GetMoments);
685 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 // The bitmasked value choices are as follows:
687 // unset: In this case (the default) JSBSim would only print
688 // out the normally expected messages, essentially echoing
689 // the config files as they are read. If the environment
690 // variable is not set, debug_lvl is set to 1 internally
691 // 0: This requests JSBSim not to output any messages
693 // 1: This value explicity requests the normal JSBSim
695 // 2: This value asks for a message to be printed out when
696 // a class is instantiated
697 // 4: When this value is set, a message is displayed when a
698 // FGModel object executes its Run() method
699 // 8: When this value is set, various runtime state variables
700 // are printed out periodically
701 // 16: When set various parameters are sanity checked and
702 // a message is printed out when they go out of bounds
704 void FGPropulsion::Debug(int from)
706 if (debug_lvl <= 0) return;
708 if (debug_lvl & 1) { // Standard console startup message output
709 if (from == 2) { // Loader
710 cout << endl << " Propulsion:" << endl;
713 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
714 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
715 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
717 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
719 if (debug_lvl & 8 ) { // Runtime state variables
721 if (debug_lvl & 16) { // Sanity checking
723 if (debug_lvl & 64) {
724 if (from == 0) { // Constructor
725 cout << IdSrc << endl;
726 cout << IdHdr << endl;