]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGPropulsion.cpp
Frederic Bouvier:
[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, numEngines));
235         } else if (engType == "FG_PISTON") {
236           Engines.push_back(new FGPiston(FDMExec, Cfg_ptr, numEngines));
237         } else if (engType == "FG_TURBINE") {
238           Engines.push_back(new FGTurbine(FDMExec, Cfg_ptr, numEngines));
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, numEngines));
246         } else if (engType == "FG_ELECTRIC") {
247           Engines.push_back(new FGElectric(FDMExec, Cfg_ptr, numEngines));
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         numEngines++;
285
286       } else {
287
288         cerr << fgred << "\n  Could not read engine config file: " << underon <<
289                     engineFileName + ".xml" << underoff << fgdef << endl;
290         return false;
291       }
292
293     } else if (token == "AC_TANK") {              // ============== READING TANKS
294
295       if (debug_lvl > 0) cout << "\n    Reading tank definition" << endl;
296       Tanks.push_back(new FGTank(AC_cfg, FDMExec));
297       switch(Tanks[numTanks]->GetType()) {
298       case FGTank::ttFUEL:
299         numSelectedFuelTanks++;
300         numFuelTanks++;
301         break;
302       case FGTank::ttOXIDIZER:
303         numSelectedOxiTanks++;
304         numOxiTanks++;
305         break;
306       }
307
308       numTanks++;
309     }
310     AC_cfg->GetNextConfigLine();
311   }
312
313   CalculateTankInertias();
314   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
315
316   return true;
317 }
318
319 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320
321 string FGPropulsion::GetPropulsionStrings(void)
322 {
323   string PropulsionStrings = "";
324   bool firstime = true;
325
326   for (unsigned int i=0;i<Engines.size();i++) {
327     if (firstime)  firstime = false;
328     else           PropulsionStrings += ", ";
329
330     PropulsionStrings += Engines[i]->GetEngineLabels();
331   }
332
333   return PropulsionStrings;
334 }
335
336 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337
338 string FGPropulsion::GetPropulsionValues(void)
339 {
340   string PropulsionValues = "";
341   bool firstime = true;
342
343   for (unsigned int i=0;i<Engines.size();i++) {
344     if (firstime)  firstime = false;
345     else           PropulsionValues += ", ";
346
347     PropulsionValues += Engines[i]->GetEngineValues();
348   }
349
350   return PropulsionValues;
351 }
352
353 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354
355 FGColumnVector3& FGPropulsion::GetTanksMoment(void)
356 {
357   iTank = Tanks.begin();
358   vXYZtank_arm.InitMatrix();
359   while (iTank < Tanks.end()) {
360     vXYZtank_arm(eX) += (*iTank)->GetXYZ(eX)*(*iTank)->GetContents();
361     vXYZtank_arm(eY) += (*iTank)->GetXYZ(eY)*(*iTank)->GetContents();
362     vXYZtank_arm(eZ) += (*iTank)->GetXYZ(eZ)*(*iTank)->GetContents();
363     iTank++;
364   }
365   return vXYZtank_arm;
366 }
367
368 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369
370 double FGPropulsion::GetTanksWeight(void)
371 {
372   double Tw = 0.0;
373
374   iTank = Tanks.begin();
375   while (iTank < Tanks.end()) {
376     Tw += (*iTank)->GetContents();
377     iTank++;
378   }
379   return Tw;
380 }
381
382 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383
384 FGMatrix33& FGPropulsion::CalculateTankInertias(void)
385 {
386   unsigned int size;
387
388   size = Tanks.size();
389   if (size == 0) return tankJ;
390
391   tankJ = FGMatrix33();
392
393   for (unsigned int i=0; i<size; i++)
394     tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
395                                                Tanks[i]->GetXYZ() );
396
397   return tankJ;
398 }
399
400 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401
402 void FGPropulsion::SetMagnetos(int setting)
403 {
404   if (ActiveEngine < 0) {
405     for (unsigned i=0; i<Engines.size(); i++) {
406       ((FGPiston*)Engines[i])->SetMagnetos(setting);
407     }
408   } else {
409     ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
410   }
411 }
412
413 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414
415 void FGPropulsion::SetStarter(int setting)
416 {
417   if (ActiveEngine < 0) {
418     for (unsigned i=0; i<Engines.size(); i++) {
419       if (setting == 0)
420         Engines[i]->SetStarter(false);
421       else
422         Engines[i]->SetStarter(true);
423     }
424   } else {
425     if (setting == 0)
426       Engines[ActiveEngine]->SetStarter(false);
427     else
428       Engines[ActiveEngine]->SetStarter(true);
429   }
430 }
431
432 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433
434 void FGPropulsion::SetCutoff(int setting)
435 {
436   if (ActiveEngine < 0) {
437     for (unsigned i=0; i<Engines.size(); i++) {
438       if (setting == 0)
439         ((FGTurbine*)Engines[i])->SetCutoff(false);
440       else
441         ((FGTurbine*)Engines[i])->SetCutoff(true);
442     }
443   } else {
444     if (setting == 0)
445       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
446     else
447       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
448   }
449 }
450
451 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
452
453 void FGPropulsion::SetActiveEngine(int engine)
454 {
455   if (engine >= Engines.size() || engine < 0)
456     ActiveEngine = -1;
457   else
458     ActiveEngine = engine;
459 }
460
461 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462
463 double FGPropulsion::Transfer(int source, int target, double amount)
464 {
465  double shortage, overage;
466
467   if (source == -1) {
468      shortage = 0.0;
469   } else {
470      shortage = Tanks[source]->Drain(amount);
471   }
472   if (target == -1) {
473      overage = 0.0;
474   } else {
475      overage = Tanks[target]->Fill(amount - shortage);
476   }
477   return overage;
478 }
479
480 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481
482 void FGPropulsion::DoRefuel(double time_slice)
483 {
484   double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
485   int TanksNotFull = 0;
486
487   for (unsigned int i=0; i<numTanks; i++) {
488     if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
489   }
490
491   if (TanksNotFull) {
492     for (unsigned int i=0; i<numTanks; i++) {
493       if (Tanks[i]->GetPctFull() < 99.99)
494           Transfer(-1, i, fillrate/TanksNotFull);
495     }
496   }
497 }
498
499 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500
501 void FGPropulsion::bind(void)
502 {
503   typedef double (FGPropulsion::*PMF)(int) const;
504   typedef int (FGPropulsion::*iPMF)(void) const;
505
506   PropertyManager->Tie("propulsion/magneto_cmd", this,
507                        (iPMF)0, &FGPropulsion::SetMagnetos, true);
508   PropertyManager->Tie("propulsion/starter_cmd", this,
509                        (iPMF)0, &FGPropulsion::SetStarter,  true);
510   PropertyManager->Tie("propulsion/cutoff_cmd", this,
511                        (iPMF)0, &FGPropulsion::SetCutoff,   true);
512
513   PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
514                        (PMF)&FGPropulsion::GetForces);
515   PropertyManager->Tie("forces/fby-prop-lbs", this,2,
516                        (PMF)&FGPropulsion::GetForces);
517   PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
518                        (PMF)&FGPropulsion::GetForces);
519   PropertyManager->Tie("moments/l-prop-lbsft", this,1,
520                        (PMF)&FGPropulsion::GetMoments);
521   PropertyManager->Tie("moments/m-prop-lbsft", this,2,
522                        (PMF)&FGPropulsion::GetMoments);
523   PropertyManager->Tie("moments/n-prop-lbsft", this,3,
524                        (PMF)&FGPropulsion::GetMoments);
525
526   PropertyManager->Tie("propulsion/active_engine", this,
527            (iPMF)&FGPropulsion::GetActiveEngine, &FGPropulsion::SetActiveEngine, true);
528 }
529
530 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
531
532 void FGPropulsion::unbind(void)
533 {
534   PropertyManager->Untie("propulsion/magneto_cmd");
535   PropertyManager->Untie("propulsion/starter_cmd");
536   PropertyManager->Untie("propulsion/cutoff_cmd");
537   PropertyManager->Untie("propulsion/active_engine");
538   PropertyManager->Untie("forces/fbx-prop-lbs");
539   PropertyManager->Untie("forces/fby-prop-lbs");
540   PropertyManager->Untie("forces/fbz-prop-lbs");
541   PropertyManager->Untie("moments/l-prop-lbsft");
542   PropertyManager->Untie("moments/m-prop-lbsft");
543   PropertyManager->Untie("moments/n-prop-lbsft");
544 }
545
546 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 //    The bitmasked value choices are as follows:
548 //    unset: In this case (the default) JSBSim would only print
549 //       out the normally expected messages, essentially echoing
550 //       the config files as they are read. If the environment
551 //       variable is not set, debug_lvl is set to 1 internally
552 //    0: This requests JSBSim not to output any messages
553 //       whatsoever.
554 //    1: This value explicity requests the normal JSBSim
555 //       startup messages
556 //    2: This value asks for a message to be printed out when
557 //       a class is instantiated
558 //    4: When this value is set, a message is displayed when a
559 //       FGModel object executes its Run() method
560 //    8: When this value is set, various runtime state variables
561 //       are printed out periodically
562 //    16: When set various parameters are sanity checked and
563 //       a message is printed out when they go out of bounds
564
565 void FGPropulsion::Debug(int from)
566 {
567   if (debug_lvl <= 0) return;
568
569   if (debug_lvl & 1) { // Standard console startup message output
570     if (from == 0) { // Constructor
571
572     }
573   }
574   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
575     if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
576     if (from == 1) cout << "Destroyed:    FGPropulsion" << endl;
577   }
578   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
579   }
580   if (debug_lvl & 8 ) { // Runtime state variables
581   }
582   if (debug_lvl & 16) { // Sanity checking
583   }
584   if (debug_lvl & 64) {
585     if (from == 0) { // Constructor
586       cout << IdSrc << endl;
587       cout << IdHdr << endl;
588     }
589   }
590 }
591 }