]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGPropulsion.cpp
Sync w. JSBSim CVS
[flightgear.git] / src / FDM / JSBSim / FGPropulsion.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGPropulsion.cpp
4  Author:       Jon S. Berndt
5  Date started: 08/20/00
6  Purpose:      Encapsulates the set of engines and tanks associated
7                with this aircraft
8
9  ------------- Copyright (C) 2000  Jon S. Berndt (jsb@hal-pc.org) -------------
10
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15
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 General Public License for more
19  details.
20
21  You should have received a copy of the GNU 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.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
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:
33
34 1) The appropriate engine type instance is created
35 2) At least one tank object is created, and is linked to an engine.
36
37 At Run time each engines Calculate() method is called.
38
39 HISTORY
40 --------------------------------------------------------------------------------
41 08/20/00   JSB   Created
42
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 INCLUDES
45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46
47 #include "FGPropulsion.h"
48 #include "FGRocket.h"
49 #include "FGTurbine.h"
50 #include "FGPiston.h"
51 #include "FGElectric.h"
52 #include "FGPropertyManager.h"
53
54 namespace JSBSim {
55
56 static const char *IdSrc = "$Id$";
57 static const char *IdHdr = ID_PROPULSION;
58
59 extern short debug_lvl;
60
61
62 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 CLASS IMPLEMENTATION
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
65
66 FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
67 {
68   Name = "FGPropulsion";
69
70   numSelectedFuelTanks = numSelectedOxiTanks = 0;
71   numTanks = numEngines = 0;
72   numOxiTanks = numFuelTanks = 0;
73   ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
74   tankJ.InitMatrix();
75   refuel = false;
76
77   bind();
78
79   Debug(0);
80 }
81
82 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83
84 FGPropulsion::~FGPropulsion()
85 {
86   for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
87   Engines.clear();
88   unbind();
89   Debug(1);
90 }
91
92 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93
94 bool FGPropulsion::Run(void)
95 {
96   if (FGModel::Run()) return true;
97
98   double dt = State->Getdt();
99
100   vForces.InitMatrix();
101   vMoments.InitMatrix();
102
103   for (unsigned int i=0; i<numEngines; i++) {
104     Engines[i]->Calculate();
105     vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
106     vMoments += Engines[i]->GetMoments();     // sum body frame moments
107   }
108
109   for (unsigned int i=0; i<numTanks; i++) {
110     Tanks[i]->Calculate( dt * rate );
111   }     
112
113   if (refuel) DoRefuel( dt * rate );
114
115   return false;
116 }
117
118 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119
120 bool FGPropulsion::GetSteadyState(void)
121 {
122   double currentThrust = 0, lastThrust=-1;
123   int steady_count,j=0;
124   bool steady=false;
125
126   vForces.InitMatrix();
127   vMoments.InitMatrix();
128
129   if (!FGModel::Run()) {
130     for (unsigned int i=0; i<numEngines; i++) {
131       Engines[i]->SetTrimMode(true);
132       steady=false;
133       steady_count=0;
134       while (!steady && j < 6000) {
135         Engines[i]->Calculate();
136         lastThrust = currentThrust;
137         currentThrust = Engines[i]->GetThrust();
138         if (fabs(lastThrust-currentThrust) < 0.0001) {
139           steady_count++;
140           if (steady_count > 120) { steady=true; }
141         } else {
142           steady_count=0;
143         }
144         j++;
145       }
146       vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
147       vMoments += Engines[i]->GetMoments();     // sum body frame moments
148       Engines[i]->SetTrimMode(false);
149     }
150
151     return false;
152   } else {
153     return true;
154   }
155 }
156
157 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158
159 bool FGPropulsion::ICEngineStart(void)
160 {
161   int j;
162
163   vForces.InitMatrix();
164   vMoments.InitMatrix();
165
166   for (unsigned int i=0; i<numEngines; i++) {
167     Engines[i]->SetTrimMode(true);
168     j=0;
169     while (!Engines[i]->GetRunning() && j < 2000) {
170       Engines[i]->Calculate();
171       j++;
172     }
173     vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
174     vMoments += Engines[i]->GetMoments();     // sum body frame moments
175     Engines[i]->SetTrimMode(false);
176   }
177   return true;
178 }
179
180 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181
182 bool FGPropulsion::Load(FGConfigFile* AC_cfg)
183 {
184   string token, fullpath, localpath;
185   string engineFileName, engType;
186   string parameter;
187   string enginePath = FDMExec->GetEnginePath();
188   string aircraftPath = FDMExec->GetAircraftPath();
189   double xLoc, yLoc, zLoc, Pitch, Yaw;
190   int Feed;
191   bool ThrottleAdded = false;
192   FGConfigFile* Cfg_ptr = 0;
193
194 # ifndef macintosh
195       fullpath = enginePath + "/";
196       localpath = aircraftPath + "/Engines/";
197 # else
198       fullpath = enginePath + ";";
199       localpath = aircraftPath +  ";Engines;";
200 # endif
201
202   AC_cfg->GetNextConfigLine();
203
204   while ((token = AC_cfg->GetValue()) != string("/PROPULSION")) {
205
206     if (token == "AC_ENGINE") {                   // ============ READING ENGINES
207
208       engineFileName = AC_cfg->GetValue("FILE");
209
210       // Look in the Aircraft/Engines directory first
211       Cfg_ptr = 0;
212       FGConfigFile Local_cfg(localpath + engineFileName + ".xml");
213       FGConfigFile Eng_cfg(fullpath + engineFileName + ".xml");
214       if (Local_cfg.IsOpen()) {
215         Cfg_ptr = &Local_cfg;
216         if (debug_lvl > 0) cout << "\n    Reading engine from file: " << localpath
217                                                 + engineFileName + ".xml"<< endl;
218       } else {
219         if (Eng_cfg.IsOpen()) {
220           Cfg_ptr = &Eng_cfg;
221           if (debug_lvl > 0) cout << "\n    Reading engine from file: " << fullpath
222                                                 + engineFileName + ".xml"<< endl;
223         }
224       }
225
226       if (Cfg_ptr) {
227         Cfg_ptr->GetNextConfigLine();
228         engType = Cfg_ptr->GetValue();
229
230         FCS->AddThrottle();
231         ThrottleAdded = true;
232
233         if (engType == "FG_ROCKET") {
234           Engines.push_back(new FGRocket(FDMExec, Cfg_ptr));
235         } else if (engType == "FG_PISTON") {
236           Engines.push_back(new FGPiston(FDMExec, Cfg_ptr));
237         } else if (engType == "FG_TURBINE") {
238           Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr));
239         } else if (engType == "FG_SIMTURBINE") {
240           cerr << endl;
241           cerr << "The FG_SIMTURBINE engine type has been renamed to FG_TURBINE." << endl;
242           cerr << "To fix this problem, simply replace the FG_SIMTURBINE name " << endl;
243           cerr << "in your engine file to FG_TURBINE." << endl;
244           cerr << endl;
245           Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr));
246         } else if (engType == "FG_ELECTRIC") {
247           Engines.push_back(new FGElectric(FDMExec, Cfg_ptr));
248         } else {
249           cerr << fgred << "    Unrecognized engine type: " << underon << engType
250                     << underoff << " found in config file." << fgdef << endl;
251           return false;
252         }
253
254         AC_cfg->GetNextConfigLine();
255         while ((token = AC_cfg->GetValue()) != string("/AC_ENGINE")) {
256           *AC_cfg >> token;
257           if      (token == "XLOC")  { *AC_cfg >> xLoc; }
258           else if (token == "YLOC")  { *AC_cfg >> yLoc; }
259           else if (token == "ZLOC")  { *AC_cfg >> zLoc; }
260           else if (token == "PITCH") { *AC_cfg >> Pitch;}
261           else if (token == "YAW")   { *AC_cfg >> Yaw;  }
262           else if (token.find("AC_THRUSTER") != string::npos) {
263             if (debug_lvl > 0) cout << "\n    Reading thruster definition" << endl;
264               Engines.back()->LoadThruster(AC_cfg);
265               AC_cfg->GetNextConfigLine();
266           }
267           else if (token == "FEED")  {
268             *AC_cfg >> Feed;
269             Engines[numEngines]->AddFeedTank(Feed);
270             if (debug_lvl > 0) cout << "      Feed tank: " << Feed << endl;
271           } else cerr << "Unknown identifier: " << token << " in engine file: "
272                                                         << engineFileName << endl;
273         }
274
275         if (debug_lvl > 0)  {
276           cout << "      X = " << xLoc << endl;
277           cout << "      Y = " << yLoc << endl;
278           cout << "      Z = " << zLoc << endl;
279           cout << "      Pitch = " << Pitch << endl;
280           cout << "      Yaw = " << Yaw << endl;
281         }
282
283         Engines[numEngines]->SetPlacement(xLoc, yLoc, zLoc, Pitch, Yaw);
284         Engines[numEngines]->SetEngineNumber(numEngines);
285         numEngines++;
286
287       } else {
288
289         cerr << fgred << "\n  Could not read engine config file: " << underon <<
290                     engineFileName + ".xml" << underoff << fgdef << endl;
291         return false;
292       }
293
294     } else if (token == "AC_TANK") {              // ============== READING TANKS
295
296       if (debug_lvl > 0) cout << "\n    Reading tank definition" << endl;
297       Tanks.push_back(new FGTank(AC_cfg, FDMExec));
298       switch(Tanks[numTanks]->GetType()) {
299       case FGTank::ttFUEL:
300         numSelectedFuelTanks++;
301         numFuelTanks++;
302         break;
303       case FGTank::ttOXIDIZER:
304         numSelectedOxiTanks++;
305         numOxiTanks++;
306         break;
307       }
308
309       numTanks++;
310     }
311     AC_cfg->GetNextConfigLine();
312   }
313
314   CalculateTankInertias();
315   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
316
317   return true;
318 }
319
320 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321
322 string FGPropulsion::GetPropulsionStrings(void)
323 {
324   string PropulsionStrings = "";
325   bool firstime = true;
326
327   for (unsigned int i=0;i<Engines.size();i++) {
328     if (firstime)  firstime = false;
329     else           PropulsionStrings += ", ";
330
331     PropulsionStrings += Engines[i]->GetEngineLabels() + ", ";
332   }
333
334   return PropulsionStrings;
335 }
336
337 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338
339 string FGPropulsion::GetPropulsionValues(void)
340 {
341   string PropulsionValues = "";
342   bool firstime = true;
343
344   for (unsigned int i=0;i<Engines.size();i++) {
345     if (firstime)  firstime = false;
346     else           PropulsionValues += ", ";
347
348     PropulsionValues += Engines[i]->GetEngineValues() + ", ";
349   }
350
351   return PropulsionValues;
352 }
353
354 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355
356 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
357 {
358   iTank = Tanks.begin();
359   vXYZtank_arm.InitMatrix();
360   while (iTank < Tanks.end()) {
361     vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
362     vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
363     vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
364     iTank++;
365   }
366   return vXYZtank_arm;
367 }
368
369 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370
371 double FGPropulsion::GetTanksWeight(void)
372 {
373   double Tw = 0.0;
374
375   iTank = Tanks.begin();
376   while (iTank < Tanks.end()) {
377     Tw += (*iTank)->GetContents();
378     iTank++;
379   }
380   return Tw;
381 }
382
383 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384
385 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
386 {
387   unsigned int size;
388
389   size = Tanks.size();
390   if (size == 0) return tankJ;
391
392   tankJ = FGMatrix33();
393
394   for (unsigned int i=0; i<size; i++)
395     tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
396                                                Tanks[i]->GetXYZ() );
397
398   return tankJ;
399 }
400
401 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402
403 void FGPropulsion::SetMagnetos(int setting)
404 {
405   if (ActiveEngine < 0) {
406     for (unsigned i=0; i<Engines.size(); i++) {
407       ((FGPiston*)Engines[i])->SetMagnetos(setting);
408     }
409   } else {
410     ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
411   }
412 }
413
414 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415
416 void FGPropulsion::SetStarter(int setting)
417 {
418   if (ActiveEngine < 0) {
419     for (unsigned i=0; i<Engines.size(); i++) {
420       if (setting == 0)
421         Engines[i]->SetStarter(false);
422       else
423         Engines[i]->SetStarter(true);
424     }
425   } else {
426     if (setting == 0)
427       Engines[ActiveEngine]->SetStarter(false);
428     else
429       Engines[ActiveEngine]->SetStarter(true);
430   }
431 }
432
433 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434
435 void FGPropulsion::SetCutoff(int setting)
436 {
437   if (ActiveEngine < 0) {
438     for (unsigned i=0; i<Engines.size(); i++) {
439       if (setting == 0)
440         ((FGTurbine*)Engines[i])->SetCutoff(false);
441       else
442         ((FGTurbine*)Engines[i])->SetCutoff(true);
443     }
444   } else {
445     if (setting == 0)
446       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
447     else
448       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
449   }
450 }
451
452 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453
454 void FGPropulsion::SetActiveEngine(int engine)
455 {
456   if (engine >= Engines.size() || engine < 0)
457     ActiveEngine = -1;
458   else
459     ActiveEngine = engine;
460 }
461
462 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463
464 double FGPropulsion::Transfer(int source, int target, double amount)
465 {
466  double shortage, overage;
467
468   if (source == -1) {
469      shortage = 0.0;
470   } else {
471      shortage = Tanks[source]->Drain(amount);
472   }
473   if (target == -1) {
474      overage = 0.0;
475   } else {
476      overage = Tanks[target]->Fill(amount - shortage);
477   }
478   return overage;
479 }
480
481 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482
483 void FGPropulsion::DoRefuel(double time_slice)
484 {
485   double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
486   int TanksNotFull = 0;
487
488   for (unsigned int i=0; i<numTanks; i++) {
489     if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
490   }
491
492   if (TanksNotFull) {
493     for (unsigned int i=0; i<numTanks; i++) {
494       if (Tanks[i]->GetPctFull() < 99.99)
495           Transfer(-1, i, fillrate/TanksNotFull);
496     }
497   }      
498 }
499
500 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501
502 void FGPropulsion::bind(void)
503 {
504   typedef double (FGPropulsion::*PMF)(int) const;
505   typedef int (FGPropulsion::*iPMF)(void) const;
506
507   PropertyManager->Tie("propulsion/magneto_cmd", this,
508                        (iPMF)0, &FGPropulsion::SetMagnetos, true);
509   PropertyManager->Tie("propulsion/starter_cmd", this,
510                        (iPMF)0, &FGPropulsion::SetStarter,  true);
511   PropertyManager->Tie("propulsion/cutoff_cmd", this,
512                        (iPMF)0, &FGPropulsion::SetCutoff,   true);
513
514   PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
515                        (PMF)&FGPropulsion::GetForces);
516   PropertyManager->Tie("forces/fby-prop-lbs", this,2,
517                        (PMF)&FGPropulsion::GetForces);
518   PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
519                        (PMF)&FGPropulsion::GetForces);
520   PropertyManager->Tie("moments/l-prop-lbsft", this,1,
521                        (PMF)&FGPropulsion::GetMoments);
522   PropertyManager->Tie("moments/m-prop-lbsft", this,2,
523                        (PMF)&FGPropulsion::GetMoments);
524   PropertyManager->Tie("moments/n-prop-lbsft", this,3,
525                        (PMF)&FGPropulsion::GetMoments);
526
527   PropertyManager->Tie("propulsion/active_engine", this,
528            (iPMF)&FGPropulsion::GetActiveEngine, &FGPropulsion::SetActiveEngine, true);
529 }
530
531 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532
533 void FGPropulsion::unbind(void)
534 {
535   PropertyManager->Untie("propulsion/magneto_cmd");
536   PropertyManager->Untie("propulsion/starter_cmd");
537   PropertyManager->Untie("propulsion/cutoff_cmd");
538   PropertyManager->Untie("propulsion/active_engine");
539   PropertyManager->Untie("forces/fbx-prop-lbs");
540   PropertyManager->Untie("forces/fby-prop-lbs");
541   PropertyManager->Untie("forces/fbz-prop-lbs");
542   PropertyManager->Untie("moments/l-prop-lbsft");
543   PropertyManager->Untie("moments/m-prop-lbsft");
544   PropertyManager->Untie("moments/n-prop-lbsft");
545 }
546
547 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
548 //    The bitmasked value choices are as follows:
549 //    unset: In this case (the default) JSBSim would only print
550 //       out the normally expected messages, essentially echoing
551 //       the config files as they are read. If the environment
552 //       variable is not set, debug_lvl is set to 1 internally
553 //    0: This requests JSBSim not to output any messages
554 //       whatsoever.
555 //    1: This value explicity requests the normal JSBSim
556 //       startup messages
557 //    2: This value asks for a message to be printed out when
558 //       a class is instantiated
559 //    4: When this value is set, a message is displayed when a
560 //       FGModel object executes its Run() method
561 //    8: When this value is set, various runtime state variables
562 //       are printed out periodically
563 //    16: When set various parameters are sanity checked and
564 //       a message is printed out when they go out of bounds
565
566 void FGPropulsion::Debug(int from)
567 {
568   if (debug_lvl <= 0) return;
569
570   if (debug_lvl & 1) { // Standard console startup message output
571     if (from == 0) { // Constructor
572
573     }
574   }
575   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
576     if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
577     if (from == 1) cout << "Destroyed:    FGPropulsion" << endl;
578   }
579   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
580   }
581   if (debug_lvl & 8 ) { // Runtime state variables
582   }
583   if (debug_lvl & 16) { // Sanity checking
584   }
585   if (debug_lvl & 64) {
586     if (from == 0) { // Constructor
587       cout << IdSrc << endl;
588       cout << IdHdr << endl;
589     }
590   }
591 }
592 }