52 : TankNumber(tank_number)
54 string token, strFuelName;
60 InitialTemperature = Temperature = -9999.0;
61 Ixx = Iyy = Izz = 0.0;
63 Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
65 InitialStandpipe = 0.0;
66 Capacity = 0.00001; UnusableVol = 0.0;
67 Priority = InitialPriority = 1;
69 vXYZ_drain.InitMatrix();
70 ixx_unit = iyy_unit = izz_unit = 1.0;
74 if (type ==
"FUEL") Type =
ttFUEL;
75 else if (type ==
"OXIDIZER") Type =
ttOXIDIZER;
80 else cerr << el->
ReadFrom() <<
"No location found for this tank."
116 <<
"Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl;
121 cerr << el->
ReadFrom() <<
"Tank capacity (" << Capacity
122 <<
" lbs) is lower than the amount of unusable fuel (" <<
GetUnusable()
123 <<
" lbs) for tank " << tank_number
124 <<
"! Did you accidentally swap unusable and capacity?" << endl;
125 throw(
"tank definition error");
127 if (Contents > Capacity) {
128 cerr << el->
ReadFrom() <<
"Tank content (" << Contents
129 <<
" lbs) is greater than tank capacity (" << Capacity
130 <<
" lbs) for tank " << tank_number
131 <<
"! Did you accidentally swap contents and capacity?" << endl;
132 throw(
"tank definition error");
135 cerr << el->
ReadFrom() <<
"Tank content (" << Contents
136 <<
" lbs) is lower than the amount of unusable fuel (" <<
GetUnusable()
137 <<
" lbs) for tank " << tank_number << endl;
140 PctFull = 100.0*Contents/Capacity;
149 else if (strGType ==
"ENDBURNING") grainType =
gtENDBURNING;
150 else if (strGType ==
"FUNCTION") {
159 throw(
"For tank "+to_string(TankNumber)+
" and when grain_config is specified an ixx must be specified when the FUNCTION grain type is specified.");
169 throw(
"For tank "+to_string(TankNumber)+
" and when grain_config is specified an iyy must be specified when the FUNCTION grain type is specified.");
179 throw(
"For tank "+to_string(TankNumber)+
" and when grain_config is specified an izz must be specified when the FUNCTION grain type is specified.");
183 cerr << el->
ReadFrom() <<
"Unknown propellant grain type specified"
195 if (Radius <= InnerRadius) {
196 const string s(
"The bore diameter should be smaller than the total grain diameter!");
197 cerr << element_Grain->
ReadFrom() << endl << s << endl;
200 Volume =
M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius);
203 Volume =
M_PI * Length * Radius * Radius;
210 const string s(
"Unknown grain type found in this rocket engine definition.");
211 cerr << el->
ReadFrom() << endl << s << endl;
215 Density = (Capacity*
lbtoslug)/Volume;
220 if (Temperature != -9999.0) InitialTemperature = Temperature =
FahrenheitToCelsius(Temperature);
221 Area = 40.0 * pow(Capacity/1975, 0.666666667);
226 bind(PropertyManager);
245 PctFull = 100.0*Contents/Capacity;
254 return vXYZ_drain + (Contents/Capacity)*(vXYZ - vXYZ_drain);
261 return vXYZ_drain(idx) + (Contents/Capacity)*(vXYZ(idx)-vXYZ_drain(idx));
268 double remaining = Contents - used;
276 remaining = Contents;
279 PctFull = 100.0*Contents/Capacity;
289 double overage = 0.0;
293 if (Contents > Capacity) {
294 overage = Contents - Capacity;
298 PctFull = Contents/Capacity*100.0;
311 if (Contents > Capacity) {
315 PctFull = Contents/Capacity*100.0;
333 if(ExternalFlow < 0.)
Drain( -ExternalFlow *dt);
334 else Fill(ExternalFlow * dt);
336 if (Temperature == -9999.0)
return 0.0;
337 double HeatCapacity = 900.0;
338 double TempFlowFactor = 1.115;
339 double Tdiff = TAT_C - Temperature;
341 if (fabs(Tdiff) > 0.1 && Contents > 0.01) {
342 dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity);
345 return Temperature += (dTemp + dTemp);
365void FGTank::CalculateInertias(
void)
369 double Rad2 = Radius*Radius;
374 Volume = (Contents*
lbtoslug)/Density;
375 }
else if (Contents <= 0.0) {
378 const string s(
" Solid propellant grain density is zero!");
379 cerr << endl << s << endl;
380 throw BaseException(s);
385 InnerRadius = sqrt(Rad2 - Volume/(
M_PI * Length));
386 RadSumSqr = (Rad2 + InnerRadius*InnerRadius)/144.0;
387 Ixx = 0.5*Mass*RadSumSqr;
388 Iyy = Mass*(3.0*RadSumSqr + Length*Length/144.0)/12.0;
392 Length = Volume/(
M_PI*Rad2);
393 Ixx = 0.5*Mass*Rad2/144.0;
394 Iyy = Mass*(3.0*Rad2 + Length*Length)/(144.0*12.0);
398 Ixx = function_ixx->GetValue()*ixx_unit;
399 Iyy = function_iyy->GetValue()*iyy_unit;
400 Izz = function_izz->GetValue()*izz_unit;
404 const string s(
"Unknown grain type found.");
406 throw BaseException(s);
412 if (Radius > 0.0) Ixx = Iyy = Izz = Mass * InertiaFactor * 0.4 * Radius * Radius / 144.0;
421 if (
name ==
"AVGAS")
return 6.02;
422 else if (
name ==
"JET-A")
return 6.74;
423 else if (
name ==
"JET-A1")
return 6.74;
424 else if (
name ==
"JET-B")
return 6.48;
425 else if (
name ==
"JP-1")
return 6.76;
426 else if (
name ==
"JP-2")
return 6.38;
427 else if (
name ==
"JP-3")
return 6.34;
428 else if (
name ==
"JP-4")
return 6.48;
429 else if (
name ==
"JP-5")
return 6.81;
430 else if (
name ==
"JP-6")
return 6.55;
431 else if (
name ==
"JP-7")
return 6.61;
432 else if (
name ==
"JP-8")
return 6.66;
433 else if (
name ==
"JP-8+100")
return 6.66;
436 else if (
name ==
"RP-1")
return 6.73;
437 else if (
name ==
"T-1")
return 6.88;
438 else if (
name ==
"ETHANOL")
return 6.58;
439 else if (
name ==
"HYDRAZINE")
return 8.61;
440 else if (
name ==
"F-34")
return 6.66;
441 else if (
name ==
"F-35")
return 6.74;
442 else if (
name ==
"F-40")
return 6.48;
443 else if (
name ==
"F-44")
return 6.81;
444 else if (
name ==
"AVTAG")
return 6.48;
445 else if (
name ==
"AVCAT")
return 6.81;
447 cerr <<
"Unknown fuel type specified: "<<
name << endl;
457 string property_name, base_property_name;
459 property_name = base_property_name +
"/contents-lbs";
462 property_name = base_property_name +
"/unusable-volume-gal";
465 property_name = base_property_name +
"/pct-full";
467 property_name = base_property_name +
"/density-lbs_per_gal";
470 property_name = base_property_name +
"/priority";
473 property_name = base_property_name +
"/external-flow-rate-pps";
476 property_name = base_property_name +
"/local-ixx-slug_ft2";
478 property_name = base_property_name +
"/local-iyy-slug_ft2";
480 property_name = base_property_name +
"/local-izz-slug_ft2";
483 property_name = base_property_name +
"/x-position";
485 property_name = base_property_name +
"/y-position";
487 property_name = base_property_name +
"/z-position";
511void FGTank::Debug(
int from)
517 cout <<
" " << type <<
" tank holds " << Capacity <<
" lbs. " << type << endl;
518 cout <<
" currently at " << PctFull <<
"% of maximum capacity" << endl;
519 cout <<
" Tank location (X, Y, Z): " << vXYZ(
eX) <<
", " << vXYZ(
eY) <<
", " << vXYZ(
eZ) << endl;
520 cout <<
" Effective radius: " << Radius <<
" inches" << endl;
521 cout <<
" Initial temperature: " << Temperature <<
" Fahrenheit" << endl;
522 cout <<
" Priority: " << Priority << endl;
526 if (from == 0) cout <<
"Instantiated: FGTank" << endl;
527 if (from == 1) cout <<
"Destroyed: FGTank" << endl;
double FindElementValueAsNumberConvertTo(const std::string &el, const std::string &target_units)
Searches for the named element and converts and returns the data belonging to it.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
FGColumnVector3 FindElementTripletConvertTo(const std::string &target_units)
Composes a 3-element column vector for the supplied location or orientation.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
std::string FindElementValue(const std::string &el="")
Searches for the named element and returns the string data belonging to it.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
Element * FindElement(const std::string &el="")
Searches for a specified element.
This class implements a 3 element column vector.
FGPropertyManager * GetPropertyManager(void)
Returns a pointer to the property manager object.
Represents a mathematical function.
static constexpr double FahrenheitToCelsius(double fahrenheit)
Converts from degrees Fahrenheit to degrees Celsius.
static constexpr double lbtoslug
static std::string CreateIndexedPropertyName(const std::string &Property, int index)
void Tie(const std::string &name, T *pointer)
Tie a property to an external variable.
void SetContentsGallons(double gallons)
double GetPctFull(void) const
Gets the tank fill level.
double GetLocationY(void) const
void SetUnusableVolume(double volume)
Sets the volume of unusable fuel in the tank.
void ResetToIC(void)
Resets the tank parameters to the initial conditions.
double GetUnusableVolume(void) const
Returns the unusable volume of fuel in the tank.
double Drain(double used)
Removes fuel from the tank.
double GetContents(void) const
Gets the contents of the tank.
double GetLocationZ(void) const
double GetIyy(void) const
void SetExternalFlow(double f)
double GetIxx(void) const
double Calculate(double dt, double TempC)
Performs local, tanks-specific calculations, such as fuel temperature.
void SetTemperature(double temp)
void SetLocationX(double x)
void SetLocationZ(double z)
double GetLocationX(void) const
void SetLocationY(double y)
void SetStandpipe(double amount)
double GetIzz(void) const
double ProcessFuelName(const std::string &name)
Returns the density of a named fuel type.
FGColumnVector3 GetXYZ(void) const
int GetPriority(void) const
double Fill(double amount)
void SetContents(double amount)
double GetUnusable(void) const
Returns the amount of unusable fuel in the tank.
double GetExternalFlow(void) const
double GetDensity(void) const
Returns the fuel density.
FGTank(FGFDMExec *exec, Element *el, int tank_number)
Constructor.