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/propulsion/FGRocket.h>
49 #include <models/propulsion/FGTurbine.h>
50 #include <models/propulsion/FGPiston.h>
51 #include <models/propulsion/FGElectric.h>
52 #include <models/propulsion/FGTurboProp.h>
53 #include <input_output/FGPropertyManager.h>
54 #include <input_output/FGXMLParse.h>
55 #include <math/FGColumnVector3.h>
60 static const char *IdSrc = "$Id$";
61 static const char *IdHdr = ID_PROPULSION;
63 extern short debug_lvl;
66 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
70 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
72 Name = "FGPropulsion";
74 InitializedEngines = 0;
75 numSelectedFuelTanks = numSelectedOxiTanks = 0;
76 numTanks = numEngines = 0;
77 numOxiTanks = numFuelTanks = 0;
78 ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
80 refuel = dump = false;
83 TotalFuelQuantity = 0.0;
89 HaveElectricEngine = false;
90 HasInitializedEngines = false;
95 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 FGPropulsion::~FGPropulsion()
99 for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
101 for (unsigned int i=0; i<Tanks.size(); i++) delete Tanks[i];
106 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 bool FGPropulsion::InitModel(void)
110 if (!FGModel::InitModel()) return false;
112 for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
114 for (unsigned int i=0; i<numEngines; i++) {
115 switch (Engines[i]->GetType()) {
116 case FGEngine::etPiston:
117 ((FGPiston*)Engines[i])->ResetToIC();
118 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
120 case FGEngine::etTurbine:
121 ((FGTurbine*)Engines[i])->ResetToIC();
122 if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
132 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134 bool FGPropulsion::Run(void)
138 if (FGModel::Run()) return true;
139 if (FDMExec->Holding()) return false;
141 double dt = State->Getdt();
143 vForces.InitMatrix();
144 vMoments.InitMatrix();
146 for (i=0; i<numEngines; i++) {
147 Engines[i]->Calculate();
148 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
149 vMoments += Engines[i]->GetMoments(); // sum body frame moments
152 TotalFuelQuantity = 0.0;
153 for (i=0; i<numTanks; i++) {
154 Tanks[i]->Calculate( dt * rate );
155 if (Tanks[i]->GetType() == FGTank::ttFUEL) {
156 TotalFuelQuantity += Tanks[i]->GetContents();
160 if (refuel) DoRefuel( dt * rate );
161 if (dump) DumpFuel( dt * rate );
166 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 bool FGPropulsion::GetSteadyState(void)
170 double currentThrust = 0, lastThrust = -1;
171 int steady_count = 0, j = 0;
174 vForces.InitMatrix();
175 vMoments.InitMatrix();
177 if (!FGModel::Run()) {
178 for (unsigned int i=0; i<numEngines; i++) {
179 // cout << " Finding steady state for engine " << i << endl;
180 Engines[i]->SetTrimMode(true);
184 while (!steady && j < 6000) {
185 Engines[i]->Calculate();
186 lastThrust = currentThrust;
187 currentThrust = Engines[i]->GetThruster()->GetThrust();
188 if (fabs(lastThrust-currentThrust) < 0.0001) {
190 if (steady_count > 120) {
192 // cout << " Steady state found at thrust: " << currentThrust << " lbs." << endl;
200 // cout << " Could not find a steady state for this engine." << endl;
202 vForces += Engines[i]->GetBodyForces(); // sum body frame forces
203 vMoments += Engines[i]->GetMoments(); // sum body frame moments
204 Engines[i]->SetTrimMode(false);
213 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 void FGPropulsion::InitRunning(int n)
217 if (n > 0) { // A specific engine is supposed to be initialized
219 if (n >= (int)GetNumEngines() ) {
220 cerr << "Tried to initialize a non-existent engine!" << endl;
223 FCS->SetThrottleCmd(n,1);
224 FCS->SetMixtureCmd(n,1);
225 GetEngine(n)->InitRunning();
228 InitializedEngines = 1 << n;
229 HasInitializedEngines = true;
231 } else if (n < 0) { // -1 refers to "All Engines"
233 for (unsigned int i=0; i<GetNumEngines(); i++) {
234 FCS->SetThrottleCmd(i,1);
235 FCS->SetMixtureCmd(i,1);
236 GetEngine(i)->InitRunning();
239 InitializedEngines = -1;
240 HasInitializedEngines = true;
242 } else if (n == 0) { // No engines are to be initialized
247 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 bool FGPropulsion::Load(Element* el)
251 string type, engine_filename;
252 bool ThrottleAdded = false;
256 FGModel::Load(el); // Perform base class Load.
258 Element* engine_element = el->FindElement("engine");
259 while (engine_element) {
260 engine_filename = engine_element->GetAttributeValue("file");
262 if (engine_filename.empty()) {
263 cerr << "Engine definition did not supply an engine file." << endl;
267 engine_filename = FindEngineFullPathname(engine_filename);
268 document = LoadXMLDocument(engine_filename);
269 document->SetParent(engine_element);
271 type = document->GetName();
272 if (type == "piston_engine") {
273 HavePistonEngine = true;
274 if (!IsBound) bind();
275 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
276 } else if (type == "turbine_engine") {
277 HaveTurbineEngine = true;
278 if (!IsBound) bind();
279 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
280 } else if (type == "turboprop_engine") {
281 HaveTurboPropEngine = true;
282 if (!IsBound) bind();
283 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
284 } else if (type == "rocket_engine") {
285 HaveRocketEngine = true;
286 if (!IsBound) bind();
287 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
288 } else if (type == "electric_engine") {
289 HaveElectricEngine = true;
290 if (!IsBound) bind();
291 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
293 cerr << "Unknown engine type: " << type << endl;
298 ThrottleAdded = true;
302 engine_element = el->FindNextElement("engine");
306 // Process tank definitions
308 Element* tank_element = el->FindElement("tank");
309 while (tank_element) {
310 Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
311 if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
312 else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
313 else {cerr << "Unknown tank type specified." << endl; return false;}
315 tank_element = el->FindNextElement("tank");
317 numSelectedFuelTanks = numFuelTanks;
318 numSelectedOxiTanks = numOxiTanks;
320 CalculateTankInertias();
321 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
323 // Process fuel dump rate
324 if (el->FindElement("dump-rate"))
325 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
331 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 string FGPropulsion::FindEngineFullPathname(string engine_filename)
335 string fullpath, localpath;
336 string enginePath = FDMExec->GetEnginePath();
337 string aircraftPath = FDMExec->GetFullAircraftPath();
338 ifstream engine_file;
340 string separator = "/";
342 fullpath = enginePath + separator;
343 localpath = aircraftPath + separator + "Engines" + separator;
345 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
346 if ( !engine_file.is_open()) {
347 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
348 if ( !engine_file.is_open()) {
349 cerr << " Could not open engine file: " << engine_filename << " in path "
350 << fullpath << " or " << localpath << endl;
353 return string(localpath + engine_filename + ".xml");
356 return string(fullpath + engine_filename + ".xml");
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 ifstream* FGPropulsion::FindEngineFile(string engine_filename)
363 string fullpath, localpath;
364 string enginePath = FDMExec->GetEnginePath();
365 string aircraftPath = FDMExec->GetFullAircraftPath();
366 ifstream* engine_file = new ifstream();
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;
384 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 string FGPropulsion::GetPropulsionStrings(string delimeter)
390 string PropulsionStrings = "";
391 bool firstime = true;
394 for (i=0; i<Engines.size(); i++) {
395 if (firstime) firstime = false;
396 else PropulsionStrings += delimeter;
398 PropulsionStrings += Engines[i]->GetEngineLabels(delimeter);
400 for (i=0; i<Tanks.size(); i++) {
401 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i;
402 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i;
405 return PropulsionStrings;
408 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
410 string FGPropulsion::GetPropulsionValues(string delimeter)
414 string PropulsionValues = "";
415 bool firstime = true;
418 for (i=0; i<Engines.size(); i++) {
419 if (firstime) firstime = false;
420 else PropulsionValues += delimeter;
422 PropulsionValues += Engines[i]->GetEngineValues(delimeter);
424 for (i=0; i<Tanks.size(); i++) {
426 buf << Tanks[i]->GetContents();
429 return PropulsionValues;
432 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
436 vXYZtank_arm.InitMatrix();
437 for (unsigned int i=0; i<Tanks.size(); i++) {
438 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
439 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
440 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
445 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447 double FGPropulsion::GetTanksWeight(void)
451 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
456 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
463 if (size == 0) return tankJ;
465 tankJ = FGMatrix33();
467 for (unsigned int i=0; i<size; i++) {
468 tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
469 Tanks[i]->GetXYZ() );
470 tankJ(1,1) += Tanks[i]->GetIxx();
471 tankJ(2,2) += Tanks[i]->GetIyy();
472 tankJ(3,3) += Tanks[i]->GetIzz();
478 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 void FGPropulsion::SetMagnetos(int setting)
482 if (ActiveEngine < 0) {
483 for (unsigned i=0; i<Engines.size(); i++) {
484 // ToDo: first need to make sure the engine Type is really appropriate:
485 // do a check to see if it is of type Piston. This should be done for
486 // all of this kind of possibly across-the-board settings.
487 ((FGPiston*)Engines[i])->SetMagnetos(setting);
490 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
494 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496 void FGPropulsion::SetStarter(int setting)
498 if (ActiveEngine < 0) {
499 for (unsigned i=0; i<Engines.size(); i++) {
501 Engines[i]->SetStarter(false);
503 Engines[i]->SetStarter(true);
507 Engines[ActiveEngine]->SetStarter(false);
509 Engines[ActiveEngine]->SetStarter(true);
513 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 void FGPropulsion::SetCutoff(int setting)
517 if (ActiveEngine < 0) {
518 for (unsigned i=0; i<Engines.size(); i++) {
520 ((FGTurbine*)Engines[i])->SetCutoff(false);
522 ((FGTurbine*)Engines[i])->SetCutoff(true);
526 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
528 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
532 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 void FGPropulsion::SetActiveEngine(int engine)
536 if (engine >= (int)Engines.size() || engine < 0)
539 ActiveEngine = engine;
542 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 double FGPropulsion::Transfer(int source, int target, double amount)
546 double shortage, overage;
551 shortage = Tanks[source]->Drain(amount);
556 overage = Tanks[target]->Fill(amount - shortage);
561 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563 void FGPropulsion::DoRefuel(double time_slice)
567 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
568 int TanksNotFull = 0;
570 for (i=0; i<numTanks; i++) {
571 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
575 for (i=0; i<numTanks; i++) {
576 if (Tanks[i]->GetPctFull() < 99.99)
577 Transfer(-1, i, fillrate/TanksNotFull);
582 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 void FGPropulsion::DumpFuel(double time_slice)
587 int TanksDumping = 0;
589 for (i=0; i<numTanks; i++) {
590 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
593 if (TanksDumping == 0) return;
595 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
597 for (i=0; i<numTanks; i++) {
598 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
599 Transfer(i, -1, dump_rate_per_tank);
604 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 void FGPropulsion::SetFuelFreeze(bool f)
609 for (unsigned int i=0; i<numEngines; i++) {
610 Engines[i]->SetFuelFreeze(f);
614 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 void FGPropulsion::bind(void)
618 typedef double (FGPropulsion::*PMF)(int) const;
619 typedef int (FGPropulsion::*iPMF)(void) const;
622 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
623 if (HaveTurbineEngine) {
624 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
625 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
628 if (HavePistonEngine) {
629 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
630 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
633 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
634 &FGPropulsion::SetActiveEngine, true);
635 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
636 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
637 &FGPropulsion::SetRefuel, true);
638 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
639 &FGPropulsion::SetFuelDump, true);
640 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
641 (PMF)&FGPropulsion::GetForces);
642 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
643 (PMF)&FGPropulsion::GetForces);
644 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
645 (PMF)&FGPropulsion::GetForces);
646 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
647 (PMF)&FGPropulsion::GetMoments);
648 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
649 (PMF)&FGPropulsion::GetMoments);
650 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
651 (PMF)&FGPropulsion::GetMoments);
655 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 // The bitmasked value choices are as follows:
657 // unset: In this case (the default) JSBSim would only print
658 // out the normally expected messages, essentially echoing
659 // the config files as they are read. If the environment
660 // variable is not set, debug_lvl is set to 1 internally
661 // 0: This requests JSBSim not to output any messages
663 // 1: This value explicity requests the normal JSBSim
665 // 2: This value asks for a message to be printed out when
666 // a class is instantiated
667 // 4: When this value is set, a message is displayed when a
668 // FGModel object executes its Run() method
669 // 8: When this value is set, various runtime state variables
670 // are printed out periodically
671 // 16: When set various parameters are sanity checked and
672 // a message is printed out when they go out of bounds
674 void FGPropulsion::Debug(int from)
676 if (debug_lvl <= 0) return;
678 if (debug_lvl & 1) { // Standard console startup message output
679 if (from == 2) { // Loader
680 cout << endl << " Propulsion:" << endl;
683 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
684 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
685 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
687 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
689 if (debug_lvl & 8 ) { // Runtime state variables
691 if (debug_lvl & 16) { // Sanity checking
693 if (debug_lvl & 64) {
694 if (from == 0) { // Constructor
695 cout << IdSrc << endl;
696 cout << IdHdr << endl;