Date started: 01/21/99
Called by: FGAircraft
- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
+ ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGTank.h"
+#include "FGFDMExec.h"
+#include "input_output/FGXMLElement.h"
+#include "input_output/FGPropertyManager.h"
+#include <iostream>
+#include <cstdlib>
-using std::cerr;
-using std::endl;
-using std::cout;
+using namespace std;
namespace JSBSim {
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTank.cpp,v 1.33 2011/10/31 14:54:41 bcoconni Exp $";
static const char *IdHdr = ID_TANK;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
- : TankNumber(tank_number)
+ : TankNumber(tank_number), Exec(exec)
{
- string token;
+ string token, strFuelName;
Element* element;
Element* element_Grain;
Area = 1.0;
- Temperature = -9999.0;
- Auxiliary = exec->GetAuxiliary();
- Radius = Capacity = Contents = Standpipe = Length = InnerRadius = 0.0;
- PropertyManager = exec->GetPropertyManager();
+ Density = 6.6;
+ InitialTemperature = Temperature = -9999.0;
+ Ixx = Iyy = Izz = 0.0;
+ Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
+ PreviousUsed = 0.0;
+ ExternalFlow = 0.0;
+ InitialStandpipe = 0.0;
+ Capacity = 0.00001;
+ Priority = InitialPriority = 1;
+ PropertyManager = Exec->GetPropertyManager();
vXYZ.InitMatrix();
vXYZ_drain.InitMatrix();
InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature");
if (el->FindElement("standpipe"))
InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS");
+ if (el->FindElement("priority"))
+ InitialPriority = Priority = (int)el->FindElementValueAsNumber("priority");
+ if (el->FindElement("density"))
+ Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
+ if (el->FindElement("type"))
+ strFuelName = el->FindElementValue("type");
- Selected = true;
- if (Capacity != 0) {
- PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
- } else {
- Contents = 0;
- PctFull = 0;
+ SetPriority( InitialPriority ); // this will also set the Selected flag
+
+ if (Capacity == 0) {
+ cerr << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl;
+ Capacity = 0.00001;
+ Contents = 0.0;
}
+ PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
// Check whether this is a solid propellant "tank". Initialize it if true.
exit(-1);
}
Density = (Contents*lbtoslug)/Volume; // slugs/in^3
-
+ CalculateInertias();
}
- char property_name[80];
- snprintf(property_name, 80, "propulsion/tank[%d]/contents-lbs", TankNumber);
- PropertyManager->Tie( property_name, (FGTank*)this, &FGTank::GetContents,
+ string property_name, base_property_name;
+ base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
+ property_name = base_property_name + "/contents-lbs";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
&FGTank::SetContents );
+ property_name = base_property_name + "/priority";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
+ &FGTank::SetPriority );
+ property_name = base_property_name + "/external-flow-rate-pps";
+ PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
+ &FGTank::SetExternalFlow );
if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
Area = 40.0 * pow(Capacity/1975, 0.666666667);
+ // A named fuel type will override a previous density value
+ if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName);
+
Debug(0);
}
void FGTank::ResetToIC(void)
{
- Temperature = InitialTemperature;
- Standpipe = InitialStandpipe;
- Contents = InitialContents;
+ SetTemperature( InitialTemperature );
+ SetStandpipe ( InitialStandpipe );
+ SetContents ( InitialContents );
PctFull = 100.0*Contents/Capacity;
- Selected = true;
+ SetPriority( InitialPriority );
+ PreviousUsed = 0.0;
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-const FGColumnVector3 FGTank::GetXYZ(void)
+FGColumnVector3 FGTank::GetXYZ(void) const
{
return vXYZ_drain + (Contents/Capacity)*(vXYZ - vXYZ_drain);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-const double FGTank::GetXYZ(int idx)
+double FGTank::GetXYZ(int idx) const
{
return vXYZ_drain(idx) + (Contents/Capacity)*(vXYZ(idx)-vXYZ_drain(idx));
}
double FGTank::Drain(double used)
{
+// double AmountToDrain = 2.0*used - PreviousUsed;
double remaining = Contents - used;
if (remaining >= 0) { // Reduce contents by amount used.
Contents = 0.0;
PctFull = 0.0;
- Selected = false;
}
-
+// PreviousUsed = AmountToDrain;
if (grainType != gtUNKNOWN) CalculateInertias();
return remaining;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-double FGTank::Calculate(double dt)
+void FGTank::SetContentsGallons(double gallons)
+{
+ SetContents(gallons * Density);
+}
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTank::Calculate(double dt, double TAT_C)
{
+ if(ExternalFlow < 0.) Drain( -ExternalFlow *dt);
+ else Fill(ExternalFlow * dt);
+
if (Temperature == -9999.0) return 0.0;
double HeatCapacity = 900.0; // Joules/lbm/C
double TempFlowFactor = 1.115; // Watts/sqft/C
- double TAT = Auxiliary->GetTAT_C();
- double Tdiff = TAT - Temperature;
+ double Tdiff = TAT_C - Temperature;
double dTemp = 0.0; // Temp change due to one surface
if (fabs(Tdiff) > 0.1) {
dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity);
}
+
return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same
}
double Mass = Contents*lbtoslug;
double RadSumSqr;
double Rad2 = Radius*Radius;
- Volume = (Contents*lbtoslug)/Density; // in^3
+
+ if (Density > 0.0) {
+ Volume = (Contents*lbtoslug)/Density; // in^3
+ } else {
+ cerr << endl << " Solid propellant grain density is zero!" << endl << endl;
+ exit(-1);
+ }
switch (grainType) {
case gtCYLINDRICAL:
Ixx = 0.5*Mass*Rad2/144.0;
Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0);
break;
+ case gtUNKNOWN:
+ cerr << "Unknown grain type found." << endl;
+ exit(-1);
+ break;
}
Izz = Iyy;
}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGTank::ProcessFuelName(const std::string& name)
+{
+ if (name == "AVGAS") return 6.02;
+ else if (name == "JET-A") return 6.74;
+ else if (name == "JET-A1") return 6.74;
+ else if (name == "JET-B") return 6.48;
+ else if (name == "JP-1") return 6.76;
+ else if (name == "JP-2") return 6.38;
+ else if (name == "JP-3") return 6.34;
+ else if (name == "JP-4") return 6.48;
+ else if (name == "JP-5") return 6.81;
+ else if (name == "JP-6") return 6.55;
+ else if (name == "JP-7") return 6.61;
+ else if (name == "JP-8") return 6.66;
+ else if (name == "JP-8+100") return 6.66;
+ //else if (name == "JP-9") return 6.74;
+ //else if (name == "JPTS") return 6.74;
+ else if (name == "RP-1") return 6.73;
+ else if (name == "T-1") return 6.88;
+ else if (name == "ETHANOL") return 6.58;
+ else if (name == "HYDRAZINE")return 8.61;
+ else if (name == "F-34") return 6.66;
+ else if (name == "F-35") return 6.74;
+ else if (name == "F-40") return 6.48;
+ else if (name == "F-44") return 6.81;
+ else if (name == "AVTAG") return 6.48;
+ else if (name == "AVCAT") return 6.81;
+ else {
+ cerr << "Unknown fuel type specified: "<< name << endl;
+ }
+
+ return 6.6;
+}
+
+
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// The bitmasked value choices are as follows:
// unset: In this case (the default) JSBSim would only print
cout << " Tank location (X, Y, Z): " << vXYZ(eX) << ", " << vXYZ(eY) << ", " << vXYZ(eZ) << endl;
cout << " Effective radius: " << Radius << " inches" << endl;
cout << " Initial temperature: " << Temperature << " Fahrenheit" << endl;
+ cout << " Priority: " << Priority << endl;
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification