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 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
311 } else if (type == "turbine_engine") {
312 HaveTurbineEngine = true;
313 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
314 } else if (type == "turboprop_engine") {
315 HaveTurboPropEngine = true;
316 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
317 } else if (type == "rocket_engine") {
318 HaveRocketEngine = true;
319 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
320 } else if (type == "electric_engine") {
321 HaveElectricEngine = true;
322 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
324 cerr << "Unknown engine type: " << type << endl;
327 } catch (std::string str) {
328 cerr << endl << fgred << str << reset << endl;
332 FDMExec->GetFCS()->AddThrottle();
333 ThrottleAdded = true;
337 engine_element = el->FindNextElement("engine");
341 CalculateTankInertias();
342 if (!ThrottleAdded) FDMExec->GetFCS()->AddThrottle(); // need to have at least one throttle
344 // Process fuel dump rate
345 if (el->FindElement("dump-rate"))
346 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
348 if (!IsBound) bind();
349 PostLoad(el, PropertyManager);
354 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356 string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
358 string fullpath, localpath;
359 string enginePath = FDMExec->GetEnginePath();
360 string aircraftPath = FDMExec->GetFullAircraftPath();
361 ifstream engine_file;
363 string separator = "/";
365 fullpath = enginePath + separator;
366 localpath = aircraftPath + separator + "Engines" + separator;
368 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
369 if ( !engine_file.is_open()) {
370 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
371 if ( !engine_file.is_open()) {
372 cerr << " Could not open engine file: " << engine_filename << " in path "
373 << fullpath << " or " << localpath << endl;
376 return string(localpath + engine_filename + ".xml");
379 return string(fullpath + engine_filename + ".xml");
382 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384 ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
386 string fullpath, localpath;
387 string enginePath = FDMExec->GetEnginePath();
388 string aircraftPath = FDMExec->GetFullAircraftPath();
389 ifstream* engine_file = new ifstream();
391 string separator = "/";
393 fullpath = enginePath + separator;
394 localpath = aircraftPath + separator + "Engines" + separator;
396 engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
397 if ( !engine_file->is_open()) {
398 engine_file->open(string(localpath + engine_filename + ".xml").c_str());
399 if ( !engine_file->is_open()) {
400 cerr << " Could not open engine file: " << engine_filename << " in path "
401 << fullpath << " or " << localpath << endl;
407 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409 string FGPropulsion::GetPropulsionStrings(const string& delimiter) const
413 string PropulsionStrings = "";
414 bool firstime = true;
417 for (i=0; i<Engines.size(); i++) {
418 if (firstime) firstime = false;
419 else PropulsionStrings += delimiter;
421 PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
423 for (i=0; i<Tanks.size(); i++) {
424 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
425 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
428 return PropulsionStrings;
431 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433 string FGPropulsion::GetPropulsionValues(const string& delimiter) const
437 string PropulsionValues = "";
438 bool firstime = true;
441 for (i=0; i<Engines.size(); i++) {
442 if (firstime) firstime = false;
443 else PropulsionValues += delimiter;
445 PropulsionValues += Engines[i]->GetEngineValues(delimiter);
447 for (i=0; i<Tanks.size(); i++) {
449 buf << Tanks[i]->GetContents();
452 return PropulsionValues;
455 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
459 vXYZtank_arm.InitMatrix();
460 for (unsigned int i=0; i<Tanks.size(); i++) {
461 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
462 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
463 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
468 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470 double FGPropulsion::GetTanksWeight(void)
474 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
479 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
486 if (size == 0) return tankJ;
488 tankJ = FGMatrix33();
490 for (unsigned int i=0; i<size; i++) {
491 tankJ += FDMExec->GetMassBalance()->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
492 Tanks[i]->GetXYZ() );
493 tankJ(1,1) += Tanks[i]->GetIxx();
494 tankJ(2,2) += Tanks[i]->GetIyy();
495 tankJ(3,3) += Tanks[i]->GetIzz();
501 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503 void FGPropulsion::SetMagnetos(int setting)
505 if (ActiveEngine < 0) {
506 for (unsigned i=0; i<Engines.size(); i++) {
507 // ToDo: first need to make sure the engine Type is really appropriate:
508 // do a check to see if it is of type Piston. This should be done for
509 // all of this kind of possibly across-the-board settings.
510 ((FGPiston*)Engines[i])->SetMagnetos(setting);
513 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
517 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 void FGPropulsion::SetStarter(int setting)
521 if (ActiveEngine < 0) {
522 for (unsigned i=0; i<Engines.size(); i++) {
524 Engines[i]->SetStarter(false);
526 Engines[i]->SetStarter(true);
530 Engines[ActiveEngine]->SetStarter(false);
532 Engines[ActiveEngine]->SetStarter(true);
536 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
538 void FGPropulsion::SetCutoff(int setting)
540 if (ActiveEngine < 0) {
541 for (unsigned i=0; i<Engines.size(); i++) {
543 ((FGTurbine*)Engines[i])->SetCutoff(false);
545 ((FGTurbine*)Engines[i])->SetCutoff(true);
549 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
551 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
555 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 void FGPropulsion::SetActiveEngine(int engine)
559 if (engine >= (int)Engines.size() || engine < 0)
562 ActiveEngine = engine;
565 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 double FGPropulsion::Transfer(int source, int target, double amount)
569 double shortage, overage;
574 shortage = Tanks[source]->Drain(amount);
579 overage = Tanks[target]->Fill(amount - shortage);
584 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 void FGPropulsion::DoRefuel(double time_slice)
590 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
591 int TanksNotFull = 0;
593 for (i=0; i<numTanks; i++) {
594 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
598 for (i=0; i<numTanks; i++) {
599 if (Tanks[i]->GetPctFull() < 99.99)
600 Transfer(-1, i, fillrate/TanksNotFull);
605 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607 void FGPropulsion::DumpFuel(double time_slice)
610 int TanksDumping = 0;
612 for (i=0; i<numTanks; i++) {
613 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
616 if (TanksDumping == 0) return;
618 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
620 for (i=0; i<numTanks; i++) {
621 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
622 Transfer(i, -1, dump_rate_per_tank);
627 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 void FGPropulsion::SetFuelFreeze(bool f)
632 for (unsigned int i=0; i<numEngines; i++) {
633 Engines[i]->SetFuelFreeze(f);
637 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 void FGPropulsion::bind(void)
641 typedef double (FGPropulsion::*PMF)(int) const;
642 typedef int (FGPropulsion::*iPMF)(void) const;
645 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
646 if (HaveTurbineEngine) {
647 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
648 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
651 if (HavePistonEngine) {
652 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
653 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
656 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
657 &FGPropulsion::SetActiveEngine, true);
658 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
659 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
660 &FGPropulsion::SetRefuel, true);
661 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
662 &FGPropulsion::SetFuelDump, true);
663 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
664 (PMF)&FGPropulsion::GetForces);
665 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
666 (PMF)&FGPropulsion::GetForces);
667 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
668 (PMF)&FGPropulsion::GetForces);
669 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
670 (PMF)&FGPropulsion::GetMoments);
671 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
672 (PMF)&FGPropulsion::GetMoments);
673 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
674 (PMF)&FGPropulsion::GetMoments);
678 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 // The bitmasked value choices are as follows:
680 // unset: In this case (the default) JSBSim would only print
681 // out the normally expected messages, essentially echoing
682 // the config files as they are read. If the environment
683 // variable is not set, debug_lvl is set to 1 internally
684 // 0: This requests JSBSim not to output any messages
686 // 1: This value explicity requests the normal JSBSim
688 // 2: This value asks for a message to be printed out when
689 // a class is instantiated
690 // 4: When this value is set, a message is displayed when a
691 // FGModel object executes its Run() method
692 // 8: When this value is set, various runtime state variables
693 // are printed out periodically
694 // 16: When set various parameters are sanity checked and
695 // a message is printed out when they go out of bounds
697 void FGPropulsion::Debug(int from)
699 if (debug_lvl <= 0) return;
701 if (debug_lvl & 1) { // Standard console startup message output
702 if (from == 2) { // Loader
703 cout << endl << " Propulsion:" << endl;
706 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
707 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
708 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
710 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
712 if (debug_lvl & 8 ) { // Runtime state variables
714 if (debug_lvl & 16) { // Sanity checking
716 if (debug_lvl & 64) {
717 if (from == 0) { // Constructor
718 cout << IdSrc << endl;
719 cout << IdHdr << endl;