LCOV - code coverage report
Current view: top level - models - FGPropulsion.cpp (source / functions) Hit Total Coverage
Test: JSBSim-Coverage-Statistics Lines: 170 332 51.2 %
Date: 2010-08-24 Functions: 16 29 55.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 69 209 33.0 %

           Branch data     Line data    Source code
       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 (jon@jsbsim.org) -------------
      10                 :            : 
      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
      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 Lesser General Public License for more
      19                 :            :  details.
      20                 :            : 
      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.
      24                 :            : 
      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.
      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 "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"
      60                 :            : #include <iostream>
      61                 :            : #include <sstream>
      62                 :            : #include <cstdlib>
      63                 :            : 
      64                 :            : using namespace std;
      65                 :            : 
      66                 :            : namespace JSBSim {
      67                 :            : 
      68                 :            : static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $";
      69                 :            : static const char *IdHdr = ID_PROPULSION;
      70                 :            : 
      71                 :            : extern short debug_lvl;
      72                 :            : 
      73                 :            : 
      74                 :            : /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      75                 :            : CLASS IMPLEMENTATION
      76                 :            : %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
      77                 :            : 
      78                 :          2 : FGPropulsion::FGPropulsion(FGFDMExec* exec) : FGModel(exec)
      79                 :            : {
      80                 :          1 :   Name = "FGPropulsion";
      81                 :            : 
      82                 :          1 :   InitializedEngines = 0;
      83                 :          1 :   numSelectedFuelTanks = numSelectedOxiTanks = 0;
      84                 :          1 :   numTanks = numEngines = 0;
      85                 :          1 :   numOxiTanks = numFuelTanks = 0;
      86                 :          1 :   ActiveEngine = -1; // -1: ALL, 0: Engine 1, 1: Engine 2 ...
      87                 :          1 :   tankJ.InitMatrix();
      88                 :          1 :   refuel = dump = false;
      89                 :          1 :   DumpRate = 0.0;
      90                 :          1 :   fuel_freeze = false;
      91                 :          1 :   TotalFuelQuantity = 0.0;
      92                 :            :   IsBound =
      93                 :            :   HavePistonEngine =
      94                 :            :   HaveTurbineEngine =
      95                 :            :   HaveRocketEngine =
      96                 :            :   HaveTurboPropEngine =
      97                 :          1 :   HaveElectricEngine = false;
      98                 :          1 :   HasInitializedEngines = false;
      99                 :            : 
     100                 :          1 :   Debug(0);
     101                 :          1 : }
     102                 :            : 
     103                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     104                 :            : 
     105                 :          1 : FGPropulsion::~FGPropulsion()
     106                 :            : {
     107 [ +  - ][ +  + ]:         13 :   for (unsigned int i=0; i<Engines.size(); i++) delete Engines[i];
         [ #  # ][ #  # ]
     108                 :          1 :   Engines.clear();
     109 [ +  - ][ +  + ]:          7 :   for (unsigned int i=0; i<Tanks.size(); i++) delete Tanks[i];
         [ #  # ][ #  # ]
     110                 :          1 :   Tanks.clear();
     111                 :          1 :   Debug(1);
     112                 :          2 : }
     113                 :            : 
     114                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     115                 :            : 
     116                 :          1 : bool FGPropulsion::InitModel(void)
     117                 :            : {
     118         [ -  + ]:          1 :   if (!FGModel::InitModel()) return false;
     119                 :            : 
     120         [ -  + ]:          1 :   for (unsigned int i=0; i<numTanks; i++) Tanks[i]->ResetToIC();
     121                 :            : 
     122         [ -  + ]:          1 :   for (unsigned int i=0; i<numEngines; i++) {
     123      [ #  #  # ]:          0 :     switch (Engines[i]->GetType()) {
     124                 :            :       case FGEngine::etPiston:
     125                 :          0 :         ((FGPiston*)Engines[i])->ResetToIC();
     126 [ #  # ][ #  # ]:          0 :         if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
     127                 :            :         break;
     128                 :            :       case FGEngine::etTurbine:
     129                 :          0 :         ((FGTurbine*)Engines[i])->ResetToIC();
     130 [ #  # ][ #  # ]:          0 :         if (HasInitializedEngines && (InitializedEngines & i)) InitRunning(i);
     131                 :            :         break;
     132                 :            :       default:
     133                 :            :         break;
     134                 :            :     }
     135                 :            :   }
     136                 :            : 
     137                 :          1 :   return true;
     138                 :            : }
     139                 :            : 
     140                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     141                 :            : 
     142                 :      54005 : bool FGPropulsion::Run(void)
     143                 :            : {
     144                 :            :   unsigned int i;
     145                 :            : 
     146         [ -  + ]:      54005 :   if (FGModel::Run()) return true;
     147         [ -  + ]:      54005 :   if (FDMExec->Holding()) return false;
     148                 :            : 
     149                 :      54005 :   RunPreFunctions();
     150                 :            : 
     151                 :     108010 :   double dt = FDMExec->GetDeltaT();
     152                 :            : 
     153                 :      54005 :   vForces.InitMatrix();
     154                 :      54005 :   vMoments.InitMatrix();
     155                 :            : 
     156         [ +  + ]:     702065 :   for (i=0; i<numEngines; i++) {
     157                 :     648060 :     Engines[i]->Calculate();
     158                 :     648060 :     vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
     159                 :     648060 :     vMoments += Engines[i]->GetMoments();     // sum body frame moments
     160                 :            :   }
     161                 :            : 
     162                 :      54005 :   TotalFuelQuantity = 0.0;
     163         [ +  + ]:     378035 :   for (i=0; i<numTanks; i++) {
     164                 :     324030 :     Tanks[i]->Calculate( dt * rate );
     165         [ +  + ]:     324030 :     if (Tanks[i]->GetType() == FGTank::ttFUEL) {
     166                 :     216020 :       TotalFuelQuantity += Tanks[i]->GetContents();
     167                 :            :     }
     168                 :            :   }
     169                 :            : 
     170         [ -  + ]:      54005 :   if (refuel) DoRefuel( dt * rate );
     171         [ -  + ]:      54005 :   if (dump) DumpFuel( dt * rate );
     172                 :            : 
     173                 :      54005 :   RunPostFunctions();
     174                 :            : 
     175                 :      54005 :   return false;
     176                 :            : }
     177                 :            : 
     178                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     179                 :            : 
     180                 :          0 : bool FGPropulsion::GetSteadyState(void)
     181                 :            : {
     182                 :          0 :   double currentThrust = 0, lastThrust = -1;
     183                 :          0 :   int steady_count = 0, j = 0;
     184                 :          0 :   bool steady = false;
     185                 :            : 
     186                 :          0 :   vForces.InitMatrix();
     187                 :          0 :   vMoments.InitMatrix();
     188                 :            : 
     189         [ #  # ]:          0 :   if (!FGModel::Run()) {
     190         [ #  # ]:          0 :     for (unsigned int i=0; i<numEngines; i++) {
     191                 :            : //      cout << "  Finding steady state for engine " << i << endl;
     192                 :          0 :       Engines[i]->SetTrimMode(true);
     193                 :          0 :       steady=false;
     194                 :          0 :       steady_count=0;
     195                 :          0 :       j=0;
     196 [ #  # ][ #  # ]:          0 :       while (!steady && j < 6000) {
     197                 :          0 :         Engines[i]->Calculate();
     198                 :          0 :         lastThrust = currentThrust;
     199                 :          0 :         currentThrust = Engines[i]->GetThruster()->GetThrust();
     200         [ #  # ]:          0 :         if (fabs(lastThrust-currentThrust) < 0.0001) {
     201                 :          0 :           steady_count++;
     202         [ #  # ]:          0 :           if (steady_count > 120) {
     203                 :          0 :             steady=true;
     204                 :            : //            cout << "    Steady state found at thrust: " << currentThrust << " lbs." << endl;
     205                 :            :           }
     206                 :            :         } else {
     207                 :          0 :           steady_count=0;
     208                 :            :         }
     209                 :          0 :         j++;
     210                 :            :       }
     211                 :            : //      if (j >= 6000) {
     212                 :            : //        cout << "    Could not find a steady state for this engine." << endl;
     213                 :            : //      }
     214                 :          0 :       vForces  += Engines[i]->GetBodyForces();  // sum body frame forces
     215                 :          0 :       vMoments += Engines[i]->GetMoments();     // sum body frame moments
     216                 :          0 :       Engines[i]->SetTrimMode(false);
     217                 :            :     }
     218                 :            : 
     219                 :          0 :     return false;
     220                 :            :   } else {
     221                 :          0 :     return true;
     222                 :            :   }
     223                 :            : }
     224                 :            : 
     225                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     226                 :            : 
     227                 :          0 : void FGPropulsion::InitRunning(int n)
     228                 :            : {
     229         [ #  # ]:          0 :   if (n > 0) { // A specific engine is supposed to be initialized
     230                 :            : 
     231         [ #  # ]:          0 :     if (n >= (int)GetNumEngines() ) {
     232                 :          0 :       cerr << "Tried to initialize a non-existent engine!" << endl;
     233                 :          0 :       throw;
     234                 :            :     }
     235                 :          0 :     FCS->SetThrottleCmd(n,1);
     236                 :          0 :     FCS->SetMixtureCmd(n,1);
     237                 :          0 :     GetEngine(n)->InitRunning();
     238                 :          0 :     GetSteadyState();
     239                 :            : 
     240                 :          0 :     InitializedEngines = 1 << n;
     241                 :          0 :     HasInitializedEngines = true;
     242                 :            : 
     243         [ #  # ]:          0 :   } else if (n < 0) { // -1 refers to "All Engines"
     244                 :            : 
     245         [ #  # ]:          0 :     for (unsigned int i=0; i<GetNumEngines(); i++) {
     246                 :          0 :       FCS->SetThrottleCmd(i,1);
     247                 :          0 :       FCS->SetMixtureCmd(i,1);
     248                 :          0 :       GetEngine(i)->InitRunning();
     249                 :            :     }
     250                 :          0 :     GetSteadyState();
     251                 :          0 :     InitializedEngines = -1;
     252                 :          0 :     HasInitializedEngines = true;
     253                 :            : 
     254                 :            :   } else if (n == 0) { // No engines are to be initialized
     255                 :            :     // Do nothing
     256                 :            :   }
     257                 :          0 : }
     258                 :            : 
     259                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     260                 :            : 
     261                 :          1 : bool FGPropulsion::Load(Element* el)
     262                 :            : {
     263                 :          1 :   string type, engine_filename;
     264                 :          1 :   bool ThrottleAdded = false;
     265                 :            : 
     266                 :          1 :   Debug(2);
     267                 :            : 
     268                 :          1 :   FGModel::Load(el); // Perform base class Load.
     269                 :            : 
     270                 :            :   // Process tank definitions first to establish the number of fuel tanks
     271                 :            : 
     272                 :          1 :   Element* tank_element = el->FindElement("tank");
     273         [ +  + ]:          7 :   while (tank_element) {
     274                 :          6 :     Tanks.push_back(new FGTank(FDMExec, tank_element, numTanks));
     275         [ +  + ]:          6 :     if (Tanks.back()->GetType() == FGTank::ttFUEL) numFuelTanks++;
     276         [ +  - ]:          2 :     else if (Tanks.back()->GetType() == FGTank::ttOXIDIZER) numOxiTanks++;
     277                 :          0 :     else {cerr << "Unknown tank type specified." << endl; return false;}
     278                 :          6 :     numTanks++;
     279                 :          6 :     tank_element = el->FindNextElement("tank");
     280                 :            :   }
     281                 :          1 :   numSelectedFuelTanks = numFuelTanks;
     282                 :          1 :   numSelectedOxiTanks  = numOxiTanks;
     283                 :            : 
     284                 :          1 :   Element* engine_element = el->FindElement("engine");
     285         [ +  + ]:         13 :   while (engine_element) {
     286                 :         24 :     engine_filename = engine_element->GetAttributeValue("file");
     287                 :            : 
     288         [ -  + ]:         12 :     if (engine_filename.empty()) {
     289                 :          0 :       cerr << "Engine definition did not supply an engine file." << endl;
     290                 :          0 :       return false;
     291                 :            :     }
     292                 :            : 
     293                 :         24 :     engine_filename = FindEngineFullPathname(engine_filename);
     294                 :         24 :     document = LoadXMLDocument(engine_filename);
     295                 :         12 :     document->SetParent(engine_element);
     296                 :            : 
     297                 :         12 :     type = document->GetName();
     298         [ -  + ]:         12 :     if (type == "piston_engine") {
     299                 :          0 :       HavePistonEngine = true;
     300         [ #  # ]:          0 :       if (!IsBound) bind();
     301                 :          0 :       Engines.push_back(new FGPiston(FDMExec, document, numEngines));
     302         [ -  + ]:         12 :     } else if (type == "turbine_engine") {
     303                 :          0 :       HaveTurbineEngine = true;
     304         [ #  # ]:          0 :       if (!IsBound) bind();
     305                 :          0 :       Engines.push_back(new FGTurbine(FDMExec, document, numEngines));
     306         [ -  + ]:         12 :     } else if (type == "turboprop_engine") {
     307                 :          0 :       HaveTurboPropEngine = true;
     308         [ #  # ]:          0 :       if (!IsBound) bind();
     309                 :          0 :       Engines.push_back(new FGTurboProp(FDMExec, document, numEngines));
     310         [ +  - ]:         12 :     } else if (type == "rocket_engine") {
     311                 :         12 :       HaveRocketEngine = true;
     312         [ +  + ]:         12 :       if (!IsBound) bind();
     313                 :         12 :       Engines.push_back(new FGRocket(FDMExec, document, numEngines));
     314         [ #  # ]:          0 :     } else if (type == "electric_engine") {
     315                 :          0 :       HaveElectricEngine = true;
     316         [ #  # ]:          0 :       if (!IsBound) bind();
     317                 :          0 :       Engines.push_back(new FGElectric(FDMExec, document, numEngines));
     318                 :            :     } else {
     319                 :          0 :       cerr << "Unknown engine type: " << type << endl;
     320                 :          0 :       exit(-5);
     321                 :            :     }
     322                 :            : 
     323                 :         12 :     FCS->AddThrottle();
     324                 :         12 :     ThrottleAdded = true;
     325                 :            : 
     326                 :         12 :     numEngines++;
     327                 :            : 
     328                 :         12 :     engine_element = el->FindNextElement("engine");
     329                 :         12 :     ResetParser();
     330                 :            :   }
     331                 :            : 
     332                 :          1 :   CalculateTankInertias();
     333         [ -  + ]:          1 :   if (!ThrottleAdded) FCS->AddThrottle(); // need to have at least one throttle
     334                 :            : 
     335                 :            :   // Process fuel dump rate
     336         [ -  + ]:          1 :   if (el->FindElement("dump-rate"))
     337                 :          0 :     DumpRate = el->FindElementValueAsNumberConvertTo("dump-rate", "LBS/MIN");
     338                 :            : 
     339                 :          1 :   PostLoad(el, PropertyManager);
     340                 :            : 
     341                 :          1 :   return true;
     342                 :            : }
     343                 :            : 
     344                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     345                 :            : 
     346                 :         12 : string FGPropulsion::FindEngineFullPathname(const string& engine_filename)
     347                 :            : {
     348                 :         12 :   string fullpath, localpath;
     349                 :         12 :   string enginePath = FDMExec->GetEnginePath();
     350                 :         12 :   string aircraftPath = FDMExec->GetFullAircraftPath();
     351                 :         12 :   ifstream engine_file;
     352                 :            : 
     353                 :         12 :   string separator = "/";
     354                 :            : 
     355                 :         24 :   fullpath = enginePath + separator;
     356                 :         24 :   localpath = aircraftPath + separator + "Engines" + separator;
     357                 :            : 
     358                 :         12 :   engine_file.open(string(fullpath + engine_filename + ".xml").c_str());
     359         [ -  + ]:         12 :   if ( !engine_file.is_open()) {
     360                 :          0 :     engine_file.open(string(localpath + engine_filename + ".xml").c_str());
     361         [ #  # ]:          0 :       if ( !engine_file.is_open()) {
     362                 :            :         cerr << " Could not open engine file: " << engine_filename << " in path "
     363                 :          0 :              << fullpath << " or " << localpath << endl;
     364                 :          0 :         return string("");
     365                 :            :       } else {
     366                 :          0 :         return string(localpath + engine_filename + ".xml");
     367                 :            :       }
     368                 :            :   }
     369                 :         12 :   return string(fullpath + engine_filename + ".xml");
     370                 :            : }
     371                 :            : 
     372                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     373                 :            : 
     374                 :          0 : ifstream* FGPropulsion::FindEngineFile(const string& engine_filename)
     375                 :            : {
     376                 :          0 :   string fullpath, localpath;
     377                 :          0 :   string enginePath = FDMExec->GetEnginePath();
     378                 :          0 :   string aircraftPath = FDMExec->GetFullAircraftPath();
     379                 :          0 :   ifstream* engine_file = new ifstream();
     380                 :            : 
     381                 :          0 :   string separator = "/";
     382                 :            : 
     383                 :          0 :   fullpath = enginePath + separator;
     384                 :          0 :   localpath = aircraftPath + separator + "Engines" + separator;
     385                 :            : 
     386                 :          0 :   engine_file->open(string(fullpath + engine_filename + ".xml").c_str());
     387         [ #  # ]:          0 :   if ( !engine_file->is_open()) {
     388                 :          0 :     engine_file->open(string(localpath + engine_filename + ".xml").c_str());
     389         [ #  # ]:          0 :       if ( !engine_file->is_open()) {
     390                 :            :         cerr << " Could not open engine file: " << engine_filename << " in path "
     391                 :          0 :              << fullpath << " or " << localpath << endl;
     392                 :            :       }
     393                 :            :   }
     394                 :          0 :   return engine_file;
     395                 :            : }
     396                 :            : 
     397                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     398                 :            : 
     399                 :          1 : string FGPropulsion::GetPropulsionStrings(const string& delimiter)
     400                 :            : {
     401                 :            :   unsigned int i;
     402                 :            : 
     403                 :          1 :   string PropulsionStrings = "";
     404                 :          1 :   bool firstime = true;
     405                 :          1 :   stringstream buf;
     406                 :            : 
     407         [ +  + ]:         13 :   for (i=0; i<Engines.size(); i++) {
     408         [ +  + ]:         12 :     if (firstime)  firstime = false;
     409                 :         11 :     else           PropulsionStrings += delimiter;
     410                 :            : 
     411                 :         24 :     PropulsionStrings += Engines[i]->GetEngineLabels(delimiter);
     412                 :            :   }
     413         [ +  + ]:          7 :   for (i=0; i<Tanks.size(); i++) {
     414         [ +  + ]:          6 :     if (Tanks[i]->GetType() == FGTank::ttFUEL) buf << delimiter << "Fuel Tank " << i;
     415         [ +  - ]:          2 :     else if (Tanks[i]->GetType() == FGTank::ttOXIDIZER) buf << delimiter << "Oxidizer Tank " << i;
     416                 :            :   }
     417                 :            : 
     418                 :          1 :   return PropulsionStrings;
     419                 :            : }
     420                 :            : 
     421                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     422                 :            : 
     423                 :       4909 : string FGPropulsion::GetPropulsionValues(const string& delimiter)
     424                 :            : {
     425                 :            :   unsigned int i;
     426                 :            : 
     427                 :       4909 :   string PropulsionValues = "";
     428                 :       4909 :   bool firstime = true;
     429                 :       4909 :   stringstream buf;
     430                 :            : 
     431         [ +  + ]:      63817 :   for (i=0; i<Engines.size(); i++) {
     432         [ +  + ]:      58908 :     if (firstime)  firstime = false;
     433                 :      53999 :     else           PropulsionValues += delimiter;
     434                 :            : 
     435                 :     117816 :     PropulsionValues += Engines[i]->GetEngineValues(delimiter);
     436                 :            :   }
     437         [ +  + ]:      34363 :   for (i=0; i<Tanks.size(); i++) {
     438                 :      29454 :     buf << delimiter;
     439                 :      58908 :     buf << Tanks[i]->GetContents();
     440                 :            :   }
     441                 :            : 
     442                 :       4909 :   return PropulsionValues;
     443                 :            : }
     444                 :            : 
     445                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     446                 :            : 
     447                 :      54006 : FGColumnVector3& FGPropulsion::GetTanksMoment(void)
     448                 :            : {
     449                 :      54006 :   vXYZtank_arm.InitMatrix();
     450         [ +  + ]:     378042 :   for (unsigned int i=0; i<Tanks.size(); i++) {
     451                 :     324036 :     vXYZtank_arm(eX) += Tanks[i]->GetXYZ(eX) * Tanks[i]->GetContents();
     452                 :     324036 :     vXYZtank_arm(eY) += Tanks[i]->GetXYZ(eY) * Tanks[i]->GetContents();
     453                 :     324036 :     vXYZtank_arm(eZ) += Tanks[i]->GetXYZ(eZ) * Tanks[i]->GetContents();
     454                 :            :   }
     455                 :      54006 :   return vXYZtank_arm;
     456                 :            : }
     457                 :            : 
     458                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     459                 :            : 
     460                 :      54007 : double FGPropulsion::GetTanksWeight(void)
     461                 :            : {
     462                 :      54007 :   double Tw = 0.0;
     463                 :            : 
     464         [ +  + ]:     378043 :   for (unsigned int i=0; i<Tanks.size(); i++) Tw += Tanks[i]->GetContents();
     465                 :            : 
     466                 :      54007 :   return Tw;
     467                 :            : }
     468                 :            : 
     469                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     470                 :            : 
     471                 :      54007 : FGMatrix33& FGPropulsion::CalculateTankInertias(void)
     472                 :            : {
     473                 :            :   unsigned int size;
     474                 :            : 
     475                 :     108014 :   size = Tanks.size();
     476         [ -  + ]:      54007 :   if (size == 0) return tankJ;
     477                 :            : 
     478                 :      54007 :   tankJ = FGMatrix33();
     479                 :            : 
     480         [ +  + ]:     378049 :   for (unsigned int i=0; i<size; i++) {
     481                 :            :     tankJ += MassBalance->GetPointmassInertia( lbtoslug * Tanks[i]->GetContents(),
     482                 :     648084 :                                                Tanks[i]->GetXYZ() );
     483                 :    1296168 :     tankJ(1,1) += Tanks[i]->GetIxx();
     484                 :    1296168 :     tankJ(2,2) += Tanks[i]->GetIyy();
     485                 :    1296168 :     tankJ(3,3) += Tanks[i]->GetIzz();
     486                 :            :   }
     487                 :            : 
     488                 :      54007 :   return tankJ;
     489                 :            : }
     490                 :            : 
     491                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     492                 :            : 
     493                 :          0 : void FGPropulsion::SetMagnetos(int setting)
     494                 :            : {
     495         [ #  # ]:          0 :   if (ActiveEngine < 0) {
     496         [ #  # ]:          0 :     for (unsigned i=0; i<Engines.size(); i++) {
     497                 :            :       // ToDo: first need to make sure the engine Type is really appropriate:
     498                 :            :       //   do a check to see if it is of type Piston. This should be done for
     499                 :            :       //   all of this kind of possibly across-the-board settings.
     500                 :          0 :       ((FGPiston*)Engines[i])->SetMagnetos(setting);
     501                 :            :     }
     502                 :            :   } else {
     503                 :          0 :     ((FGPiston*)Engines[ActiveEngine])->SetMagnetos(setting);
     504                 :            :   }
     505                 :          0 : }
     506                 :            : 
     507                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     508                 :            : 
     509                 :          0 : void FGPropulsion::SetStarter(int setting)
     510                 :            : {
     511         [ #  # ]:          0 :   if (ActiveEngine < 0) {
     512         [ #  # ]:          0 :     for (unsigned i=0; i<Engines.size(); i++) {
     513         [ #  # ]:          0 :       if (setting == 0)
     514                 :          0 :         Engines[i]->SetStarter(false);
     515                 :            :       else
     516                 :          0 :         Engines[i]->SetStarter(true);
     517                 :            :     }
     518                 :            :   } else {
     519         [ #  # ]:          0 :     if (setting == 0)
     520                 :          0 :       Engines[ActiveEngine]->SetStarter(false);
     521                 :            :     else
     522                 :          0 :       Engines[ActiveEngine]->SetStarter(true);
     523                 :            :   }
     524                 :          0 : }
     525                 :            : 
     526                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     527                 :            : 
     528                 :          0 : void FGPropulsion::SetCutoff(int setting)
     529                 :            : {
     530         [ #  # ]:          0 :   if (ActiveEngine < 0) {
     531         [ #  # ]:          0 :     for (unsigned i=0; i<Engines.size(); i++) {
     532         [ #  # ]:          0 :       if (setting == 0)
     533                 :          0 :         ((FGTurbine*)Engines[i])->SetCutoff(false);
     534                 :            :       else
     535                 :          0 :         ((FGTurbine*)Engines[i])->SetCutoff(true);
     536                 :            :     }
     537                 :            :   } else {
     538         [ #  # ]:          0 :     if (setting == 0)
     539                 :          0 :       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
     540                 :            :     else
     541                 :          0 :       ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
     542                 :            :   }
     543                 :          0 : }
     544                 :            : 
     545                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     546                 :            : 
     547                 :          0 : void FGPropulsion::SetActiveEngine(int engine)
     548                 :            : {
     549 [ #  # ][ #  # ]:          0 :   if (engine >= (int)Engines.size() || engine < 0)
                 [ #  # ]
     550                 :          0 :     ActiveEngine = -1;
     551                 :            :   else
     552                 :          0 :     ActiveEngine = engine;
     553                 :          0 : }
     554                 :            : 
     555                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     556                 :            : 
     557                 :          0 : double FGPropulsion::Transfer(int source, int target, double amount)
     558                 :            : {
     559                 :            :  double shortage, overage;
     560                 :            : 
     561         [ #  # ]:          0 :   if (source == -1) {
     562                 :          0 :      shortage = 0.0;
     563                 :            :   } else {
     564                 :          0 :      shortage = Tanks[source]->Drain(amount);
     565                 :            :   }
     566         [ #  # ]:          0 :   if (target == -1) {
     567                 :          0 :      overage = 0.0;
     568                 :            :   } else {
     569                 :          0 :      overage = Tanks[target]->Fill(amount - shortage);
     570                 :            :   }
     571                 :          0 :   return overage;
     572                 :            : }
     573                 :            : 
     574                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     575                 :            : 
     576                 :          0 : void FGPropulsion::DoRefuel(double time_slice)
     577                 :            : {
     578                 :            :   unsigned int i;
     579                 :            : 
     580                 :          0 :   double fillrate = 100 * time_slice;   // 100 lbs/sec = 6000 lbs/min
     581                 :          0 :   int TanksNotFull = 0;
     582                 :            : 
     583         [ #  # ]:          0 :   for (i=0; i<numTanks; i++) {
     584         [ #  # ]:          0 :     if (Tanks[i]->GetPctFull() < 99.99) ++TanksNotFull;
     585                 :            :   }
     586                 :            : 
     587         [ #  # ]:          0 :   if (TanksNotFull) {
     588         [ #  # ]:          0 :     for (i=0; i<numTanks; i++) {
     589         [ #  # ]:          0 :       if (Tanks[i]->GetPctFull() < 99.99)
     590                 :          0 :           Transfer(-1, i, fillrate/TanksNotFull);
     591                 :            :     }
     592                 :            :   }
     593                 :          0 : }
     594                 :            : 
     595                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     596                 :            : 
     597                 :          0 : void FGPropulsion::DumpFuel(double time_slice)
     598                 :            : {
     599                 :            :   unsigned int i;
     600                 :          0 :   int TanksDumping = 0;
     601                 :            : 
     602         [ #  # ]:          0 :   for (i=0; i<numTanks; i++) {
     603         [ #  # ]:          0 :     if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) ++TanksDumping;
     604                 :            :   }
     605                 :            : 
     606         [ #  # ]:          0 :   if (TanksDumping == 0) return;
     607                 :            : 
     608                 :          0 :   double dump_rate_per_tank = DumpRate / 60.0 * time_slice / TanksDumping;
     609                 :            : 
     610         [ #  # ]:          0 :   for (i=0; i<numTanks; i++) {
     611         [ #  # ]:          0 :     if (Tanks[i]->GetContents() > Tanks[i]->GetStandpipe()) {
     612                 :          0 :       Transfer(i, -1, dump_rate_per_tank);
     613                 :            :     }
     614                 :            :   }
     615                 :            : }
     616                 :            : 
     617                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     618                 :            : 
     619                 :          0 : void FGPropulsion::SetFuelFreeze(bool f)
     620                 :            : {
     621                 :          0 :   fuel_freeze = f;
     622         [ #  # ]:          0 :   for (unsigned int i=0; i<numEngines; i++) {
     623                 :          0 :     Engines[i]->SetFuelFreeze(f);
     624                 :            :   }
     625                 :          0 : }
     626                 :            : 
     627                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     628                 :            : 
     629                 :          1 : void FGPropulsion::bind(void)
     630                 :            : {
     631                 :            :   typedef double (FGPropulsion::*PMF)(int) const;
     632                 :            :   typedef int (FGPropulsion::*iPMF)(void) const;
     633                 :            : 
     634                 :          1 :   IsBound = true;
     635                 :          1 :   PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, true);
     636         [ -  + ]:          1 :   if (HaveTurbineEngine) {
     637                 :          0 :     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
     638                 :          0 :     PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   true);
     639                 :            :   }
     640                 :            : 
     641         [ -  + ]:          1 :   if (HavePistonEngine) {
     642                 :          0 :     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  true);
     643                 :          0 :     PropertyManager->Tie("propulsion/magneto_cmd", this, (iPMF)0, &FGPropulsion::SetMagnetos, true);
     644                 :            :   }
     645                 :            : 
     646                 :            :   PropertyManager->Tie("propulsion/active_engine", this, (iPMF)&FGPropulsion::GetActiveEngine,
     647                 :          1 :                         &FGPropulsion::SetActiveEngine, true);
     648                 :          2 :   PropertyManager->Tie("propulsion/total-fuel-lbs", this, &FGPropulsion::GetTotalFuelQuantity);
     649                 :            :   PropertyManager->Tie("propulsion/refuel", this, &FGPropulsion::GetRefuel,
     650                 :          1 :                         &FGPropulsion::SetRefuel, true);
     651                 :            :   PropertyManager->Tie("propulsion/fuel_dump", this, &FGPropulsion::GetFuelDump,
     652                 :          1 :                         &FGPropulsion::SetFuelDump, true);
     653                 :            :   PropertyManager->Tie("forces/fbx-prop-lbs", this,1,
     654                 :          1 :                        (PMF)&FGPropulsion::GetForces);
     655                 :            :   PropertyManager->Tie("forces/fby-prop-lbs", this,2,
     656                 :          1 :                        (PMF)&FGPropulsion::GetForces);
     657                 :            :   PropertyManager->Tie("forces/fbz-prop-lbs", this,3,
     658                 :          1 :                        (PMF)&FGPropulsion::GetForces);
     659                 :            :   PropertyManager->Tie("moments/l-prop-lbsft", this,1,
     660                 :          1 :                        (PMF)&FGPropulsion::GetMoments);
     661                 :            :   PropertyManager->Tie("moments/m-prop-lbsft", this,2,
     662                 :          1 :                        (PMF)&FGPropulsion::GetMoments);
     663                 :            :   PropertyManager->Tie("moments/n-prop-lbsft", this,3,
     664                 :          1 :                        (PMF)&FGPropulsion::GetMoments);
     665                 :            : 
     666                 :          1 : }
     667                 :            : 
     668                 :            : //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     669                 :            : //    The bitmasked value choices are as follows:
     670                 :            : //    unset: In this case (the default) JSBSim would only print
     671                 :            : //       out the normally expected messages, essentially echoing
     672                 :            : //       the config files as they are read. If the environment
     673                 :            : //       variable is not set, debug_lvl is set to 1 internally
     674                 :            : //    0: This requests JSBSim not to output any messages
     675                 :            : //       whatsoever.
     676                 :            : //    1: This value explicity requests the normal JSBSim
     677                 :            : //       startup messages
     678                 :            : //    2: This value asks for a message to be printed out when
     679                 :            : //       a class is instantiated
     680                 :            : //    4: When this value is set, a message is displayed when a
     681                 :            : //       FGModel object executes its Run() method
     682                 :            : //    8: When this value is set, various runtime state variables
     683                 :            : //       are printed out periodically
     684                 :            : //    16: When set various parameters are sanity checked and
     685                 :            : //       a message is printed out when they go out of bounds
     686                 :            : 
     687                 :          3 : void FGPropulsion::Debug(int from)
     688                 :            : {
     689         [ +  - ]:          3 :   if (debug_lvl <= 0) return;
     690                 :            : 
     691         [ +  - ]:          3 :   if (debug_lvl & 1) { // Standard console startup message output
     692         [ +  + ]:          3 :     if (from == 2) { // Loader
     693                 :          1 :       cout << endl << "  Propulsion:" << endl;
     694                 :            :     }
     695                 :            :   }
     696         [ -  + ]:          3 :   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
     697         [ #  # ]:          0 :     if (from == 0) cout << "Instantiated: FGPropulsion" << endl;
     698         [ #  # ]:          0 :     if (from == 1) cout << "Destroyed:    FGPropulsion" << endl;
     699                 :            :   }
     700                 :          3 :   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
     701                 :            :   }
     702                 :          3 :   if (debug_lvl & 8 ) { // Runtime state variables
     703                 :            :   }
     704                 :          3 :   if (debug_lvl & 16) { // Sanity checking
     705                 :            :   }
     706         [ -  + ]:          3 :   if (debug_lvl & 64) {
     707         [ #  # ]:          0 :     if (from == 0) { // Constructor
     708                 :          0 :       cout << IdSrc << endl;
     709                 :          0 :       cout << IdHdr << endl;
     710                 :            :     }
     711                 :            :   }
     712                 :            : }
     713 [ +  + ][ +  - ]:         12 : }

Generated by: LCOV version 1.9