1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 Module: FGPropulsion.cpp
6 Purpose: Encapsulates the set of engines and tanks associated
9 ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.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]->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 >= 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 Element* engine_element = el->FindElement("engine");
257 while (engine_element) {
258 engine_filename = engine_element->GetAttributeValue("file");
260 if (engine_filename.empty()) {
261 cerr << "Engine definition did not supply an engine file." << endl;
265 engine_filename = FindEngineFullPathname(engine_filename);
266 document = LoadXMLDocument(engine_filename);
267 document->SetParent(engine_element);
269 type = document->GetName();
270 if (type == "piston_engine") {
271 HavePistonEngine = true;
272 if (!IsBound) bind();
273 Engines.push_back(new FGPiston(FDMExec, document, numEngines));
274 } else if (type == "turbine_engine") {
275 HaveTurbineEngine = true;
276 if (!IsBound) bind();
277 Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
278 } else if (type == "turboprop_engine") {
279 HaveTurboPropEngine = true;
280 if (!IsBound) bind();
281 Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
282 } else if (type == "rocket_engine") {
283 HaveRocketEngine = true;
284 if (!IsBound) bind();
285 Engines.push_back(new FGRocket(FDMExec, document, numEngines));
286 } else if (type == "electric_engine") {
287 HaveElectricEngine = true;
288 if (!IsBound) bind();
289 Engines.push_back(new FGElectric(FDMExec, document, numEngines));
291 cerr << "Unknown engine type: " << type << endl;
296 ThrottleAdded = true;
300 engine_element = el->FindNextElement("engine");
304 // Process tank definitions
306 Element* tank_element = el->FindElement("tank");
307 while (tank_element) {
308 Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
309 if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
310 else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
311 else {cerr << "Unknown tank type specified." << endl; return false;}
313 tank_element = el->FindNextElement("tank");
315 numSelectedFuelTanks = numFuelTanks;
316 numSelectedOxiTanks = numOxiTanks;
318 CalculateTankInertias();
319 if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
321 // Process fuel dump rate
322 if (el->FindElement("dump-rate"))
323 DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
329 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331 string FGPropulsion::FindEngineFullPathname(string engine_filename)
333 string fullpath, localpath;
334 string enginePath = FDMExec->GetEnginePath();
335 string aircraftPath = FDMExec->GetFullAircraftPath();
336 ifstream engine_file;
338 string separator = "/";
340 fullpath = enginePath + separator;
341 localpath = aircraftPath + separator + "Engines" + separator;
343 engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
344 if ( !engine_file.is_open()) {
345 engine_file.open(string(localpath + engine_filename + ".xml").c_str());
346 if ( !engine_file.is_open()) {
347 cerr << " Could not open engine file: " << engine_filename << " in path "
348 << fullpath << " or " << localpath << endl;
351 return string(localpath + engine_filename + ".xml");
354 return string(fullpath + engine_filename + ".xml");
357 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359 ifstream* FGPropulsion::FindEngineFile(string engine_filename)
361 string fullpath, localpath;
362 string enginePath = FDMExec->GetEnginePath();
363 string aircraftPath = FDMExec->GetFullAircraftPath();
364 ifstream* engine_file = new ifstream();
366 string separator = "/";
368 fullpath = enginePath + separator;
369 localpath = aircraftPath + separator + "Engines" + separator;
371 engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
372 if ( !engine_file->is_open()) {
373 engine_file->open(string(localpath + engine_filename + ".xml").c_str());
374 if ( !engine_file->is_open()) {
375 cerr << " Could not open engine file: " << engine_filename << " in path "
376 << fullpath << " or " << localpath << endl;
382 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384 string FGPropulsion::GetPropulsionStrings(string delimeter)
388 string PropulsionStrings = "";
389 bool firstime = true;
392 for (i=0; i<Engines.size(); i++) {
393 if (firstime) firstime = false;
394 else PropulsionStrings += delimeter;
396 PropulsionStrings += Engines[i]->GetEngineLabels(delimeter);
398 for (i=0; i<Tanks.size(); i++) {
399 if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimeter << "Fuel Tank " << i;
400 else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimeter << "Oxidizer Tank " << i;
403 return PropulsionStrings;
406 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
408 string FGPropulsion::GetPropulsionValues(string delimeter)
412 string PropulsionValues = "";
413 bool firstime = true;
416 for (i=0; i<Engines.size(); i++) {
417 if (firstime) firstime = false;
418 else PropulsionValues += delimeter;
420 PropulsionValues += Engines[i]->GetEngineValues(delimeter);
422 for (i=0; i<Tanks.size(); i++) {
424 buf << Tanks[i]->GetContents();
427 return PropulsionValues;
430 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
434 vXYZtank_arm.InitMatrix();
435 for (unsigned int i=0; i<Tanks.size(); i++) {
436 vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
437 vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
438 vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
443 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 double FGPropulsion::GetTanksWeight(void)
449 for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
454 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
461 if (size == 0) return tankJ;
463 tankJ = FGMatrix33();
465 for (unsigned int i=0; i<size; i++) {
466 tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
467 Tanks[i]->GetXYZ() );
468 tankJ(1,1) += Tanks[i]->GetIxx();
469 tankJ(2,2) += Tanks[i]->GetIyy();
470 tankJ(3,3) += Tanks[i]->GetIzz();
476 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478 void FGPropulsion::SetMagnetos(int setting)
480 if (ActiveEngine < 0) {
481 for (unsigned i=0; i<Engines.size(); i++) {
482 // ToDo: first need to make sure the engine Type is really appropriate:
483 // do a check to see if it is of type Piston. This should be done for
484 // all of this kind of possibly across-the-board settings.
485 ((FGPiston*)Engines[i])->SetMagnetos(setting);
488 ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
492 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 void FGPropulsion::SetStarter(int setting)
496 if (ActiveEngine < 0) {
497 for (unsigned i=0; i<Engines.size(); i++) {
499 Engines[i]->SetStarter(false);
501 Engines[i]->SetStarter(true);
505 Engines[ActiveEngine]->SetStarter(false);
507 Engines[ActiveEngine]->SetStarter(true);
511 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 void FGPropulsion::SetCutoff(int setting)
515 if (ActiveEngine < 0) {
516 for (unsigned i=0; i<Engines.size(); i++) {
518 ((FGTurbine*)Engines[i])->SetCutoff(false);
520 ((FGTurbine*)Engines[i])->SetCutoff(true);
524 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
526 ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
530 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 void FGPropulsion::SetActiveEngine(int engine)
534 if (engine >= (int)Engines.size() || engine < 0)
537 ActiveEngine = engine;
540 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
542 double FGPropulsion::Transfer(int source, int target, double amount)
544 double shortage, overage;
549 shortage = Tanks[source]->Drain(amount);
554 overage = Tanks[target]->Fill(amount - shortage);
559 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 void FGPropulsion::DoRefuel(double time_slice)
565 double fillrate = 100 * time_slice; // 100 lbs/sec = 6000 lbs/min
566 int TanksNotFull = 0;
568 for (i=0; i<numTanks; i++) {
569 if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
573 for (i=0; i<numTanks; i++) {
574 if (Tanks[i]->GetPctFull() < 99.99)
575 Transfer(-1, i, fillrate/TanksNotFull);
580 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 void FGPropulsion::DumpFuel(double time_slice)
585 int TanksDumping = 0;
587 for (i=0; i<numTanks; i++) {
588 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
591 if (TanksDumping == 0) return;
593 double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
595 for (i=0; i<numTanks; i++) {
596 if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
597 Transfer(i, -1, dump_rate_per_tank);
602 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 void FGPropulsion::SetFuelFreeze(bool f)
607 for (unsigned int i=0; i<numEngines; i++) {
608 Engines[i]->SetFuelFreeze(f);
612 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614 void FGPropulsion::bind(void)
616 typedef double (FGPropulsion::*PMF)(int) const;
617 typedef int (FGPropulsion::*iPMF)(void) const;
620 PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
621 if (HaveTurbineEngine) {
622 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
623 PropertyManager->Tie("propulsion/cutoff_cmd", this, (iPMF)0, &FGPropulsion::SetCutoff, true);
626 if (HavePistonEngine) {
627 PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter, true);
628 PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
631 PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
632 &FGPropulsion::SetActiveEngine, true);
633 PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
634 PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
635 &FGPropulsion::SetRefuel, true);
636 PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
637 &FGPropulsion::SetFuelDump, true);
638 PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
639 (PMF)&FGPropulsion::GetForces);
640 PropertyManager->Tie("forces/fby-prop-lbs", this,2,
641 (PMF)&FGPropulsion::GetForces);
642 PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
643 (PMF)&FGPropulsion::GetForces);
644 PropertyManager->Tie("moments/l-prop-lbsft", this,1,
645 (PMF)&FGPropulsion::GetMoments);
646 PropertyManager->Tie("moments/m-prop-lbsft", this,2,
647 (PMF)&FGPropulsion::GetMoments);
648 PropertyManager->Tie("moments/n-prop-lbsft", this,3,
649 (PMF)&FGPropulsion::GetMoments);
653 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 // The bitmasked value choices are as follows:
655 // unset: In this case (the default) JSBSim would only print
656 // out the normally expected messages, essentially echoing
657 // the config files as they are read. If the environment
658 // variable is not set, debug_lvl is set to 1 internally
659 // 0: This requests JSBSim not to output any messages
661 // 1: This value explicity requests the normal JSBSim
663 // 2: This value asks for a message to be printed out when
664 // a class is instantiated
665 // 4: When this value is set, a message is displayed when a
666 // FGModel object executes its Run() method
667 // 8: When this value is set, various runtime state variables
668 // are printed out periodically
669 // 16: When set various parameters are sanity checked and
670 // a message is printed out when they go out of bounds
672 void FGPropulsion::Debug(int from)
674 if (debug_lvl <= 0) return;
676 if (debug_lvl & 1) { // Standard console startup message output
677 if (from == 2) { // Loader
678 cout << endl << " Propulsion:" << endl;
681 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
682 if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
683 if (from == 1) cout << "Destroyed: FGPropulsion" << endl;
685 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
687 if (debug_lvl & 8 ) { // Runtime state variables
689 if (debug_lvl & 16) { // Sanity checking
691 if (debug_lvl & 64) {
692 if (from == 0) { // Constructor
693 cout << IdSrc << endl;
694 cout << IdHdr << endl;