void FGRocket::ConsumeFuel(void) { unsigned int i; FGTank* Tank; bool haveOxTanks = false; double Fshortage=0, Oshortage=0, TanksWithFuel=0, TanksWithOxidizer=0; if (FuelFreeze) return; if (TrimMode) return; // Count how many assigned tanks have fuel for this engine at this time. // If there is/are fuel tanks but no oxidizer tanks, this indicates // a solid rocket is being modeled. for (i=0; i<SourceTanks.size(); i++) { Tank = Propulsion->GetTank(SourceTanks[i]); switch(Tank->GetType()) { case FGTank::ttFUEL: if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithFuel; break; case FGTank::ttOXIDIZER: haveOxTanks = true; if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithOxidizer; break; } } // If this engine has burned out, it is starved. if (TanksWithFuel==0 || (haveOxTanks && TanksWithOxidizer==0)) { Starved = true; return; } // Expend fuel from the engine's tanks if the tank is selected as a source // for this engine. double fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel; double oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer; for (i=0; i<SourceTanks.size(); i++) { Tank = Propulsion->GetTank(SourceTanks[i]); if ( ! Tank->GetSelected()) continue; // If this tank is not selected as a source, skip it. switch(Tank->GetType()) { case FGTank::ttFUEL: Fshortage += Tank->Drain(2.0*fuelNeedPerTank - previousFuelNeedPerTank); previousFuelNeedPerTank = fuelNeedPerTank; break; case FGTank::ttOXIDIZER: Oshortage += Tank->Drain(2.0*oxiNeedPerTank - previousOxiNeedPerTank); previousOxiNeedPerTank = oxiNeedPerTank; break; } } if (Fshortage < 0.00 || (haveOxTanks && Oshortage < 0.00)) Starved = true; else Starved = false; }
string FGPropulsion::GetPropulsionTankReport() { string out=""; stringstream outstream; /*const FGMatrix33& mTkI =*/ CalculateTankInertias(); for (unsigned int i=0; i<numTanks; i++) { FGTank* tank = Tanks[i]; string tankname=""; if (tank->GetType() == FGTank::ttFUEL && tank->GetGrainType() != FGTank::gtUNKNOWN) { tankname = "Solid Fuel"; } else if (tank->GetType() == FGTank::ttFUEL) { tankname = "Fuel"; } else if (tank->GetType() == FGTank::ttOXIDIZER) { tankname = "Oxidizer"; } else { tankname = "(Unknown tank type)"; } outstream << highint << left << setw(4) << i << setw(30) << tankname << normint << right << setw(10) << tank->GetContents() << setw(8) << tank->GetXYZ(eX) << setw(8) << tank->GetXYZ(eY) << setw(8) << tank->GetXYZ(eZ) << setw(12) << tank->GetIxx() << setw(12) << tank->GetIyy() << setw(12) << tank->GetIzz() << endl; } return outstream.str(); }
void FGPropulsion::ConsumeFuel(FGEngine* engine) { if (FuelFreeze) return; if (FDMExec->GetTrimStatus()) return; unsigned int TanksWithFuel=0, CurrentFuelTankPriority=1; unsigned int TanksWithOxidizer=0, CurrentOxidizerTankPriority=1; vector <int> FeedListFuel, FeedListOxi; bool Starved = true; // Initially set Starved to true. Set to false in code below. bool hasOxTanks = false; // For this engine, // 1) Count how many fuel tanks with the current priority level have fuel // 2) If there none, then try next lower priority (higher number) - that is, // increment CurrentPriority. // 3) Build the feed list. // 4) Do the same for oxidizer tanks, if needed. // Process fuel tanks, if any while ((TanksWithFuel == 0) && (CurrentFuelTankPriority <= numTanks)) { for (unsigned int i=0; i<engine->GetNumSourceTanks(); i++) { unsigned int TankId = engine->GetSourceTank(i); FGTank* Tank = Tanks[TankId]; unsigned int TankPriority = Tank->GetPriority(); if (TankPriority != 0) { switch(Tank->GetType()) { case FGTank::ttFUEL: if ((Tank->GetContents() > 0.0) && Tank->GetSelected() && (TankPriority == CurrentFuelTankPriority)) { TanksWithFuel++; Starved = false; FeedListFuel.push_back(TankId); } break; case FGTank::ttOXIDIZER: // Skip this here (done below) break; } } } if (TanksWithFuel == 0) CurrentFuelTankPriority++; // No tanks at this priority, try next priority } bool FuelStarved = Starved; Starved = true; // Process Oxidizer tanks, if any if (engine->GetType() == FGEngine::etRocket) { while ((TanksWithOxidizer == 0) && (CurrentOxidizerTankPriority <= numTanks)) { for (unsigned int i=0; i<engine->GetNumSourceTanks(); i++) { unsigned int TankId = engine->GetSourceTank(i); FGTank* Tank = Tanks[TankId]; unsigned int TankPriority = Tank->GetPriority(); if (TankPriority != 0) { switch(Tank->GetType()) { case FGTank::ttFUEL: // Skip this here (done above) break; case FGTank::ttOXIDIZER: hasOxTanks = true; if (Tank->GetContents() > 0.0 && Tank->GetSelected() && TankPriority == CurrentOxidizerTankPriority) { TanksWithOxidizer++; if (TanksWithFuel > 0) Starved = false; FeedListOxi.push_back(TankId); } break; } } } if (TanksWithOxidizer == 0) CurrentOxidizerTankPriority++; // No tanks at this priority, try next priority } } bool OxiStarved = Starved; engine->SetStarved(FuelStarved || (hasOxTanks && OxiStarved)); // Tanks can be refilled, so be sure to reset engine Starved flag here. // No fuel or fuel/oxidizer found at any priority! // if (Starved) return; if (FuelStarved || (hasOxTanks && OxiStarved)) return; double FuelToBurn = engine->CalcFuelNeed(); // How much fuel does this engine need? double FuelNeededPerTank = FuelToBurn / TanksWithFuel; // Determine fuel needed per tank. for (unsigned int i=0; i<FeedListFuel.size(); i++) { Tanks[FeedListFuel[i]]->Drain(FuelNeededPerTank); } if (engine->GetType() == FGEngine::etRocket) { double OxidizerToBurn = engine->CalcOxidizerNeed(); // How much fuel does this engine need? double OxidizerNeededPerTank = 0; if (TanksWithOxidizer > 0) OxidizerNeededPerTank = OxidizerToBurn / TanksWithOxidizer; // Determine fuel needed per tank. for (unsigned int i=0; i<FeedListOxi.size(); i++) { Tanks[FeedListOxi[i]]->Drain(OxidizerNeededPerTank); } } }