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.39 2010/02/25 05:21:36 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)
118 if (!FGModel::InitModel()) return false;
120 for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
122 for (unsigned int i=0; i<numEngines; i++) {
123 switch (Engines[i]->GetType()) {
124 case FGEngine::etPiston:
125 ((FGPiston*)Engines[i])->ResetToIC();
126 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
128 case FGEngine::etTurbine:
129 ((FGTurbine*)Engines[i])->ResetToIC();
130 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
140 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 bool FGPropulsion::Run(void)
146 if (FGModel::Run()) return true;
147 if (FDMExec->Holding()) return false;
151 double dt = FDMExec->GetDeltaT();
153 vForces.InitMatrix();
154 vMoments.InitMatrix();
156 for (i=0; i<numEngines; i++) {
157 Engines[i]->Calculate();
158 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
159 vMoments += Engines[i]->GetMoments(); // sum body frame moments
162 TotalFuelQuantity = 0.0;
163 for (i=0; i<numTanks; i++) {
164 Tanks[i]->Calculate( dt * rate );
165 if (Tanks[i]->GetType() == FGTank::ttFUEL) {
166 TotalFuelQuantity += Tanks[i]->GetContents();
170 if (refuel) DoRefuel( dt * rate );
171 if (dump) DumpFuel( dt * rate );
178 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 bool FGPropulsion::GetSteadyState(void)
182 double currentThrust = 0, lastThrust = -1;
183 int steady_count = 0, j = 0;
186 vForces.InitMatrix();
187 vMoments.InitMatrix();
189 if (!FGModel::Run()) {
190 for (unsigned int i=0; i<numEngines; i++) {
191 // cout << " Finding steady state for engine " << i << endl;
192 Engines[i]->SetTrimMode(true);
196 while (!steady && j < 6000) {
197 Engines[i]->Calculate();
198 lastThrust = currentThrust;
199 currentThrust = Engines[i]->GetThruster()->GetThrust();
200 if (fabs(lastThrust-currentThrust) < 0.0001) {
202 if (steady_count > 120) {
204 // cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl;
212 // cout << " Could not find a steady state for this engine." << endl;
214 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
215 vMoments += Engines[i]->GetMoments(); // sum body frame moments
216 Engines[i]->SetTrimMode(false);
225 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 void FGPropulsion::InitRunning(int n)
229 if (n > 0) { // A specific engine is supposed to be initialized
231 if (n >= (int)GetNumEngines() ) {
232 cerr << "Tried to initialize a non-existent engine!" << endl;
235 FCS->SetThrottleCmd(n,1);
236 FCS->SetMixtureCmd(n,1);
237 GetEngine(n)->InitRunning();
240 InitializedEngines = 1 << n;
241 HasInitializedEngines = true;
243 } else if (n < 0) { // -1 refers to "All Engines"
245 for (unsigned int i=0; i<GetNumEngines(); i++) {
246 FCS->SetThrottleCmd(i,1);
247 FCS->SetMixtureCmd(i,1);
248 GetEngine(i)->InitRunning();
251 InitializedEngines = -1;
252 HasInitializedEngines = true;
254 } else if (n == 0) { // No engines are to be initialized
259 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 bool FGPropulsion::Load(Element* el)
263 string type, engine_filename;
264 bool ThrottleAdded = false;
268 FGModel::Load(el); // Perform base class Load.
270 // Process tank definitions first to establish the number of fuel tanks
272 Element* tank_element = el->FindElement("tank");
273 while (tank_element) {
274 Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
275 if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
276 else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
277 else {cerr << "Unknown tank type specified." << endl; return false;}
279 tank_element = el->FindNextElement("tank");
281 numSelectedFuelTanks = numFuelTanks;
282 numSelectedOxiTanks = numOxiTanks;
284 Element* engine_element = el->FindElement("engine");
285 while (engine_element) {
286 engine_filename = engine_element->GetAttributeValue("file");
288 if (engine_filename.empty()) {
289 cerr << "Engine definition did not supply an engine file." << endl;
293 engine_filename = FindEngineFullPathname(engine_filename);
294 document = LoadXMLDocument(engine_filename);
295 document->SetParent(engine_element);
297 type = document->GetName();
298 if (type == "piston_engine") {
299 HavePistonEngine = true;
300 if (!IsBound) bind();
301 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
302 } else if (type == "turbine_engine") {
303 HaveTurbineEngine = true;
304 if (!IsBound) bind();
305 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
306 } else if (type == "turboprop_engine") {
307 HaveTurboPropEngine = true;
308 if (!IsBound) bind();
309 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
310 } else if (type == "rocket_engine") {
311 HaveRocketEngine = true;
312 if (!IsBound) bind();
313 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
314 } else if (type == "electric_engine") {
315 HaveElectricEngine = true;
316 if (!IsBound) bind();
317 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
319 cerr << "Unknown engine type: " << type << endl;
324 ThrottleAdded = true;
328 engine_element = el->FindNextElement("engine");
332 CalculateTankInertias();
333 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
335 // Process fuel dump rate
336 if (el->FindElement("dump-rate"))
337 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
339 FGModel::PostLoad(el);
344 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
348 string fullpath, localpath;
349 string enginePath = FDMExec->GetEnginePath();
350 string aircraftPath = FDMExec->GetFullAircraftPath();
351 ifstream engine_file;
353 string separator = "/";
355 fullpath = enginePath + separator;
356 localpath = aircraftPath + separator + "Engines" + separator;
358 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
359 if ( !engine_file.is_open()) {
360 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
361 if ( !engine_file.is_open()) {
362 cerr << " Could not open engine file: " << engine_filename << " in path "
363 << fullpath << " or " << localpath << endl;
366 return string(localpath + engine_filename + ".xml");
369 return string(fullpath + engine_filename + ".xml");
372 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
376 string fullpath, localpath;
377 string enginePath = FDMExec->GetEnginePath();
378 string aircraftPath = FDMExec->GetFullAircraftPath();
379 ifstream* engine_file = new ifstream();
381 string separator = "/";
383 fullpath = enginePath + separator;
384 localpath = aircraftPath + separator + "Engines" + separator;
386 engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
387 if ( !engine_file->is_open()) {
388 engine_file->open(string(localpath + engine_filename + ".xml").c_str());
389 if ( !engine_file->is_open()) {
390 cerr << " Could not open engine file: " << engine_filename << " in path "
391 << fullpath << " or " << localpath << endl;
397 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 string FGPropulsion::GetPropulsionStrings(const string& delimiter)
403 string PropulsionStrings = "";
404 bool firstime = true;
407 for (i=0; i<Engines.size(); i++) {
408 if (firstime) firstime = false;
409 else PropulsionStrings += delimiter;
411 PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
413 for (i=0; i<Tanks.size(); i++) {
414 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
415 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
418 return PropulsionStrings;
421 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423 string FGPropulsion::GetPropulsionValues(const string& delimiter)
427 string PropulsionValues = "";
428 bool firstime = true;
431 for (i=0; i<Engines.size(); i++) {
432 if (firstime) firstime = false;
433 else PropulsionValues += delimiter;
435 PropulsionValues += Engines[i]->GetEngineValues(delimiter);
437 for (i=0; i<Tanks.size(); i++) {
439 buf << Tanks[i]->GetContents();
442 return PropulsionValues;
445 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
449 vXYZtank_arm.InitMatrix();
450 for (unsigned int i=0; i<Tanks.size(); i++) {
451 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
452 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
453 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
458 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460 double FGPropulsion::GetTanksWeight(void)
464 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
469 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
476 if (size == 0) return tankJ;
478 tankJ = FGMatrix33();
480 for (unsigned int i=0; i<size; i++) {
481 tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
482 Tanks[i]->GetXYZ() );
483 tankJ(1,1) += Tanks[i]->GetIxx();
484 tankJ(2,2) += Tanks[i]->GetIyy();
485 tankJ(3,3) += Tanks[i]->GetIzz();
491 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 void FGPropulsion::SetMagnetos(int setting)
495 if (ActiveEngine < 0) {
496 for (unsigned i=0; i<Engines.size(); i++) {
497 // ToDo: first need to make sure the engine Type is really appropriate:
498 // do a check to see if it is of type Piston. This should be done for
499 // all of this kind of possibly across-the-board settings.
500 ((FGPiston*)Engines[i])->SetMagnetos(setting);
503 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
507 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509 void FGPropulsion::SetStarter(int setting)
511 if (ActiveEngine < 0) {
512 for (unsigned i=0; i<Engines.size(); i++) {
514 Engines[i]->SetStarter(false);
516 Engines[i]->SetStarter(true);
520 Engines[ActiveEngine]->SetStarter(false);
522 Engines[ActiveEngine]->SetStarter(true);
526 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528 void FGPropulsion::SetCutoff(int setting)
530 if (ActiveEngine < 0) {
531 for (unsigned i=0; i<Engines.size(); i++) {
533 ((FGTurbine*)Engines[i])->SetCutoff(false);
535 ((FGTurbine*)Engines[i])->SetCutoff(true);
539 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
541 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
545 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 void FGPropulsion::SetActiveEngine(int engine)
549 if (engine >= (int)Engines.size() || engine < 0)
552 ActiveEngine = engine;
555 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 double FGPropulsion::Transfer(int source, int target, double amount)
559 double shortage, overage;
564 shortage = Tanks[source]->Drain(amount);
569 overage = Tanks[target]->Fill(amount - shortage);
574 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576 void FGPropulsion::DoRefuel(double time_slice)
580 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
581 int TanksNotFull = 0;
583 for (i=0; i<numTanks; i++) {
584 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
588 for (i=0; i<numTanks; i++) {
589 if (Tanks[i]->GetPctFull() < 99.99)
590 Transfer(-1, i, fillrate/TanksNotFull);
595 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 void FGPropulsion::DumpFuel(double time_slice)
600 int TanksDumping = 0;
602 for (i=0; i<numTanks; i++) {
603 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
606 if (TanksDumping == 0) return;
608 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
610 for (i=0; i<numTanks; i++) {
611 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
612 Transfer(i, -1, dump_rate_per_tank);
617 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 void FGPropulsion::SetFuelFreeze(bool f)
622 for (unsigned int i=0; i<numEngines; i++) {
623 Engines[i]->SetFuelFreeze(f);
627 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 void FGPropulsion::bind(void)
631 typedef double (FGPropulsion::*PMF)(int) const;
632 typedef int (FGPropulsion::*iPMF)(void) const;
635 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
636 if (HaveTurbineEngine) {
637 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
638 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
641 if (HavePistonEngine) {
642 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
643 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
646 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
647 &FGPropulsion::SetActiveEngine, true);
648 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
649 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
650 &FGPropulsion::SetRefuel, true);
651 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
652 &FGPropulsion::SetFuelDump, true);
653 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
654 (PMF)&FGPropulsion::GetForces);
655 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
656 (PMF)&FGPropulsion::GetForces);
657 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
658 (PMF)&FGPropulsion::GetForces);
659 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
660 (PMF)&FGPropulsion::GetMoments);
661 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
662 (PMF)&FGPropulsion::GetMoments);
663 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
664 (PMF)&FGPropulsion::GetMoments);
668 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669 // The bitmasked value choices are as follows:
670 // unset: In this case (the default) JSBSim would only print
671 // out the normally expected messages, essentially echoing
672 // the config files as they are read. If the environment
673 // variable is not set, debug_lvl is set to 1 internally
674 // 0: This requests JSBSim not to output any messages
676 // 1: This value explicity requests the normal JSBSim
678 // 2: This value asks for a message to be printed out when
679 // a class is instantiated
680 // 4: When this value is set, a message is displayed when a
681 // FGModel object executes its Run() method
682 // 8: When this value is set, various runtime state variables
683 // are printed out periodically
684 // 16: When set various parameters are sanity checked and
685 // a message is printed out when they go out of bounds
687 void FGPropulsion::Debug(int from)
689 if (debug_lvl <= 0) return;
691 if (debug_lvl & 1) { // Standard console startup message output
692 if (from == 2) { // Loader
693 cout << endl << " Propulsion:" << endl;
696 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
697 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
698 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
700 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
702 if (debug_lvl & 8 ) { // Runtime state variables
704 if (debug_lvl & 16) { // Sanity checking
706 if (debug_lvl & 64) {
707 if (from == 0) { // Constructor
708 cout << IdSrc << endl;
709 cout << IdHdr << endl;