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.46 2011/05/20 03:18: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)
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();
127 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
128 } catch (string str) {
133 case FGEngine::etTurbine:
134 ((FGTurbine*)Engines[i])->ResetToIC();
136 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
137 } catch (string str) {
150 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152 bool FGPropulsion::Run(bool Holding)
156 if (FGModel::Run(Holding)) return true;
157 if (Holding) return false;
161 double dt = FDMExec->GetDeltaT();
163 vForces.InitMatrix();
164 vMoments.InitMatrix();
166 for (i=0; i<numEngines; i++) {
167 Engines[i]->Calculate();
168 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
169 vMoments += Engines[i]->GetMoments(); // sum body frame moments
172 TotalFuelQuantity = 0.0;
173 for (i=0; i<numTanks; i++) {
174 Tanks[i]->Calculate( dt * rate );
175 if (Tanks[i]->GetType() == FGTank::ttFUEL) {
176 TotalFuelQuantity += Tanks[i]->GetContents();
180 if (refuel) DoRefuel( dt * rate );
181 if (dump) DumpFuel( dt * rate );
188 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 bool FGPropulsion::GetSteadyState(void)
192 double currentThrust = 0, lastThrust = -1;
193 int steady_count = 0, j = 0;
195 bool TrimMode = FDMExec->GetTrimStatus();
197 vForces.InitMatrix();
198 vMoments.InitMatrix();
200 if (!FGModel::Run(false)) {
201 FDMExec->SetTrimStatus(true);
203 for (unsigned int i=0; i<numEngines; i++) {
204 // cout << " Finding steady state for engine " << i << endl;
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
230 FDMExec->SetTrimStatus(TrimMode);
238 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 void FGPropulsion::InitRunning(int n)
242 if (n >= 0) { // A specific engine is supposed to be initialized
244 if (n >= (int)GetNumEngines() ) {
245 throw(string("Tried to initialize a non-existent engine!"));
247 FDMExec->GetFCS()->SetThrottleCmd(n,1);
248 FDMExec->GetFCS()->SetMixtureCmd(n,1);
249 GetEngine(n)->InitRunning();
252 InitializedEngines = 1 << n;
253 HasInitializedEngines = true;
255 } else if (n < 0) { // -1 refers to "All Engines"
257 for (unsigned int i=0; i<GetNumEngines(); i++) {
258 FDMExec->GetFCS()->SetThrottleCmd(i,1);
259 FDMExec->GetFCS()->SetMixtureCmd(i,1);
260 GetEngine(i)->InitRunning();
263 InitializedEngines = -1;
264 HasInitializedEngines = true;
269 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 bool FGPropulsion::Load(Element* el)
273 string type, engine_filename;
274 bool ThrottleAdded = false;
278 FGModel::Load(el); // Perform base class Load.
280 // Process tank definitions first to establish the number of fuel tanks
282 Element* tank_element = el->FindElement("tank");
283 while (tank_element) {
284 Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
285 if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
286 else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
287 else {cerr << "Unknown tank type specified." << endl; return false;}
289 tank_element = el->FindNextElement("tank");
291 numSelectedFuelTanks = numFuelTanks;
292 numSelectedOxiTanks = numOxiTanks;
294 Element* engine_element = el->FindElement("engine");
295 while (engine_element) {
296 engine_filename = engine_element->GetAttributeValue("file");
298 if (engine_filename.empty()) {
299 cerr << "Engine definition did not supply an engine file." << endl;
303 engine_filename = FindEngineFullPathname(engine_filename);
304 document = LoadXMLDocument(engine_filename);
305 document->SetParent(engine_element);
307 type = document->GetName();
309 if (type == "piston_engine") {
310 HavePistonEngine = true;
311 if (!IsBound) bind();
312 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
313 } else if (type == "turbine_engine") {
314 HaveTurbineEngine = true;
315 if (!IsBound) bind();
316 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
317 } else if (type == "turboprop_engine") {
318 HaveTurboPropEngine = true;
319 if (!IsBound) bind();
320 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
321 } else if (type == "rocket_engine") {
322 HaveRocketEngine = true;
323 if (!IsBound) bind();
324 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
325 } else if (type == "electric_engine") {
326 HaveElectricEngine = true;
327 if (!IsBound) bind();
328 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
330 cerr << "Unknown engine type: " << type << endl;
333 } catch (std::string str) {
334 cerr << endl << fgred << str << reset << endl;
338 FDMExec->GetFCS()->AddThrottle();
339 ThrottleAdded = true;
343 engine_element = el->FindNextElement("engine");
347 CalculateTankInertias();
348 if (!ThrottleAdded) FDMExec->GetFCS()->AddThrottle(); // need to have at least one throttle
350 // Process fuel dump rate
351 if (el->FindElement("dump-rate"))
352 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
354 PostLoad(el, PropertyManager);
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
363 string fullpath, localpath;
364 string enginePath = FDMExec->GetEnginePath();
365 string aircraftPath = FDMExec->GetFullAircraftPath();
366 ifstream engine_file;
368 string separator = "/";
370 fullpath = enginePath + separator;
371 localpath = aircraftPath + separator + "Engines" + separator;
373 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
374 if ( !engine_file.is_open()) {
375 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
376 if ( !engine_file.is_open()) {
377 cerr << " Could not open engine file: " << engine_filename << " in path "
378 << fullpath << " or " << localpath << endl;
381 return string(localpath + engine_filename + ".xml");
384 return string(fullpath + engine_filename + ".xml");
387 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
391 string fullpath, localpath;
392 string enginePath = FDMExec->GetEnginePath();
393 string aircraftPath = FDMExec->GetFullAircraftPath();
394 ifstream* engine_file = new ifstream();
396 string separator = "/";
398 fullpath = enginePath + separator;
399 localpath = aircraftPath + separator + "Engines" + separator;
401 engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
402 if ( !engine_file->is_open()) {
403 engine_file->open(string(localpath + engine_filename + ".xml").c_str());
404 if ( !engine_file->is_open()) {
405 cerr << " Could not open engine file: " << engine_filename << " in path "
406 << fullpath << " or " << localpath << endl;
412 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 string FGPropulsion::GetPropulsionStrings(const string& delimiter) const
418 string PropulsionStrings = "";
419 bool firstime = true;
422 for (i=0; i<Engines.size(); i++) {
423 if (firstime) firstime = false;
424 else PropulsionStrings += delimiter;
426 PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
428 for (i=0; i<Tanks.size(); i++) {
429 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
430 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
433 return PropulsionStrings;
436 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 string FGPropulsion::GetPropulsionValues(const string& delimiter) const
442 string PropulsionValues = "";
443 bool firstime = true;
446 for (i=0; i<Engines.size(); i++) {
447 if (firstime) firstime = false;
448 else PropulsionValues += delimiter;
450 PropulsionValues += Engines[i]->GetEngineValues(delimiter);
452 for (i=0; i<Tanks.size(); i++) {
454 buf << Tanks[i]->GetContents();
457 return PropulsionValues;
460 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
464 vXYZtank_arm.InitMatrix();
465 for (unsigned int i=0; i<Tanks.size(); i++) {
466 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
467 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
468 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
473 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
475 double FGPropulsion::GetTanksWeight(void)
479 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
484 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
491 if (size == 0) return tankJ;
493 tankJ = FGMatrix33();
495 for (unsigned int i=0; i<size; i++) {
496 tankJ += FDMExec->GetMassBalance()->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
497 Tanks[i]->GetXYZ() );
498 tankJ(1,1) += Tanks[i]->GetIxx();
499 tankJ(2,2) += Tanks[i]->GetIyy();
500 tankJ(3,3) += Tanks[i]->GetIzz();
506 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 void FGPropulsion::SetMagnetos(int setting)
510 if (ActiveEngine < 0) {
511 for (unsigned i=0; i<Engines.size(); i++) {
512 // ToDo: first need to make sure the engine Type is really appropriate:
513 // do a check to see if it is of type Piston. This should be done for
514 // all of this kind of possibly across-the-board settings.
515 ((FGPiston*)Engines[i])->SetMagnetos(setting);
518 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
522 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 void FGPropulsion::SetStarter(int setting)
526 if (ActiveEngine < 0) {
527 for (unsigned i=0; i<Engines.size(); i++) {
529 Engines[i]->SetStarter(false);
531 Engines[i]->SetStarter(true);
535 Engines[ActiveEngine]->SetStarter(false);
537 Engines[ActiveEngine]->SetStarter(true);
541 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543 void FGPropulsion::SetCutoff(int setting)
545 if (ActiveEngine < 0) {
546 for (unsigned i=0; i<Engines.size(); i++) {
548 ((FGTurbine*)Engines[i])->SetCutoff(false);
550 ((FGTurbine*)Engines[i])->SetCutoff(true);
554 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
556 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
560 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 void FGPropulsion::SetActiveEngine(int engine)
564 if (engine >= (int)Engines.size() || engine < 0)
567 ActiveEngine = engine;
570 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572 double FGPropulsion::Transfer(int source, int target, double amount)
574 double shortage, overage;
579 shortage = Tanks[source]->Drain(amount);
584 overage = Tanks[target]->Fill(amount - shortage);
589 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 void FGPropulsion::DoRefuel(double time_slice)
595 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
596 int TanksNotFull = 0;
598 for (i=0; i<numTanks; i++) {
599 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
603 for (i=0; i<numTanks; i++) {
604 if (Tanks[i]->GetPctFull() < 99.99)
605 Transfer(-1, i, fillrate/TanksNotFull);
610 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 void FGPropulsion::DumpFuel(double time_slice)
615 int TanksDumping = 0;
617 for (i=0; i<numTanks; i++) {
618 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
621 if (TanksDumping == 0) return;
623 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
625 for (i=0; i<numTanks; i++) {
626 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
627 Transfer(i, -1, dump_rate_per_tank);
632 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634 void FGPropulsion::SetFuelFreeze(bool f)
637 for (unsigned int i=0; i<numEngines; i++) {
638 Engines[i]->SetFuelFreeze(f);
642 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 void FGPropulsion::bind(void)
646 typedef double (FGPropulsion::*PMF)(int) const;
647 typedef int (FGPropulsion::*iPMF)(void) const;
650 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false);
651 if (HaveTurbineEngine) {
652 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false);
653 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, false);
656 if (HavePistonEngine) {
657 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, false);
658 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, false);
661 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
662 &FGPropulsion::SetActiveEngine, true);
663 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
664 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
665 &FGPropulsion::SetRefuel, true);
666 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
667 &FGPropulsion::SetFuelDump, true);
668 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
669 (PMF)&FGPropulsion::GetForces);
670 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
671 (PMF)&FGPropulsion::GetForces);
672 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
673 (PMF)&FGPropulsion::GetForces);
674 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
675 (PMF)&FGPropulsion::GetMoments);
676 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
677 (PMF)&FGPropulsion::GetMoments);
678 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
679 (PMF)&FGPropulsion::GetMoments);
683 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 // The bitmasked value choices are as follows:
685 // unset: In this case (the default) JSBSim would only print
686 // out the normally expected messages, essentially echoing
687 // the config files as they are read. If the environment
688 // variable is not set, debug_lvl is set to 1 internally
689 // 0: This requests JSBSim not to output any messages
691 // 1: This value explicity requests the normal JSBSim
693 // 2: This value asks for a message to be printed out when
694 // a class is instantiated
695 // 4: When this value is set, a message is displayed when a
696 // FGModel object executes its Run() method
697 // 8: When this value is set, various runtime state variables
698 // are printed out periodically
699 // 16: When set various parameters are sanity checked and
700 // a message is printed out when they go out of bounds
702 void FGPropulsion::Debug(int from)
704 if (debug_lvl <= 0) return;
706 if (debug_lvl & 1) { // Standard console startup message output
707 if (from == 2) { // Loader
708 cout << endl << " Propulsion:" << endl;
711 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
712 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
713 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
715 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
717 if (debug_lvl & 8 ) { // Runtime state variables
719 if (debug_lvl & 16) { // Sanity checking
721 if (debug_lvl & 64) {
722 if (from == 0) { // Constructor
723 cout << IdSrc << endl;
724 cout << IdHdr << endl;