FlightGear next
FGTank.cpp
Go to the documentation of this file.
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3 Module: FGTank.cpp
4 Author: Jon Berndt
5 Date started: 01/21/99
6 Called by: FGAircraft
7
8 ------------- Copyright (C) 1999 Jon S. Berndt (jon@jsbsim.org) -------------
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 2 of the License, or (at your option) any
13 later version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along
21 with this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 Further information about the GNU Lesser General Public License can also be
25 found on the world wide web at http://www.gnu.org.
26
27FUNCTIONAL DESCRIPTION
28--------------------------------------------------------------------------------
29See header file.
30
31HISTORY
32--------------------------------------------------------------------------------
3301/21/99 JSB Created
34
35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36INCLUDES
37%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38
39#include "FGTank.h"
40#include "FGFDMExec.h"
42
43using namespace std;
44
45namespace JSBSim {
46
47/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48CLASS IMPLEMENTATION
49%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
50
51FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
52 : TankNumber(tank_number)
53{
54 string token, strFuelName;
55 Element* element;
56 Element* element_Grain;
57 FGPropertyManager *PropertyManager = exec->GetPropertyManager();
58 Area = 1.0;
59 Density = 6.6;
60 InitialTemperature = Temperature = -9999.0;
61 Ixx = Iyy = Izz = 0.0;
62 InertiaFactor = 1.0;
63 Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
64 ExternalFlow = 0.0;
65 InitialStandpipe = 0.0;
66 Capacity = 0.00001; UnusableVol = 0.0;
67 Priority = InitialPriority = 1;
68 vXYZ.InitMatrix();
69 vXYZ_drain.InitMatrix();
70 ixx_unit = iyy_unit = izz_unit = 1.0;
71 grainType = gtUNKNOWN; // This is the default
72
73 type = el->GetAttributeValue("type");
74 if (type == "FUEL") Type = ttFUEL;
75 else if (type == "OXIDIZER") Type = ttOXIDIZER;
76 else Type = ttUNKNOWN;
77
78 element = el->FindElement("location");
79 if (element) vXYZ = element->FindElementTripletConvertTo("IN");
80 else cerr << el->ReadFrom() << "No location found for this tank."
81 << endl;
82
83 vXYZ_drain = vXYZ; // Set initial drain location to initial tank CG
84
85 element = el->FindElement("drain_location");
86 if (element) {
87 vXYZ_drain = element->FindElementTripletConvertTo("IN");
88 }
89
90 if (el->FindElement("radius"))
91 Radius = el->FindElementValueAsNumberConvertTo("radius", "IN");
92 if (el->FindElement("inertia_factor"))
93 InertiaFactor = el->FindElementValueAsNumber("inertia_factor");
94 if (el->FindElement("capacity"))
95 Capacity = el->FindElementValueAsNumberConvertTo("capacity", "LBS");
96 if (el->FindElement("contents"))
97 InitialContents = Contents = el->FindElementValueAsNumberConvertTo("contents", "LBS");
98 if (el->FindElement("unusable-volume"))
99 UnusableVol = el->FindElementValueAsNumberConvertTo("unusable-volume", "GAL");
100 if (el->FindElement("temperature"))
101 InitialTemperature = Temperature = el->FindElementValueAsNumber("temperature");
102 if (el->FindElement("standpipe"))
103 InitialStandpipe = Standpipe = el->FindElementValueAsNumberConvertTo("standpipe", "LBS");
104 if (el->FindElement("priority"))
105 InitialPriority = Priority = (int)el->FindElementValueAsNumber("priority");
106 if (el->FindElement("density"))
107 Density = el->FindElementValueAsNumberConvertTo("density", "LBS/GAL");
108 if (el->FindElement("type"))
109 strFuelName = el->FindElementValue("type");
110
111
112 SetPriority( InitialPriority ); // this will also set the Selected flag
113
114 if (Capacity == 0) {
115 cerr << el->ReadFrom()
116 << "Tank capacity must not be zero. Reset to 0.00001 lbs!" << endl;
117 Capacity = 0.00001;
118 Contents = 0.0;
119 }
120 if (Capacity <= GetUnusable()) {
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");
126 }
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");
133 }
134 if (Contents < GetUnusable()) {
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;
138 }
139
140 PctFull = 100.0*Contents/Capacity; // percent full; 0 to 100.0
141
142 // Check whether this is a solid propellant "tank". Initialize it if true.
143
144 element_Grain = el->FindElement("grain_config");
145 if (element_Grain) {
146
147 strGType = element_Grain->GetAttributeValue("type");
148 if (strGType == "CYLINDRICAL") grainType = gtCYLINDRICAL;
149 else if (strGType == "ENDBURNING") grainType = gtENDBURNING;
150 else if (strGType == "FUNCTION") {
151 grainType = gtFUNCTION;
152 if (element_Grain->FindElement("ixx") != 0) {
153 Element* element_ixx = element_Grain->FindElement("ixx");
154 if (element_ixx->GetAttributeValue("unit") == "KG*M2") ixx_unit = 1.0/1.35594;
155 if (element_ixx->FindElement("function") != 0) {
156 function_ixx = new FGFunction(exec, element_ixx->FindElement("function"));
157 }
158 } else {
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.");
160 }
161
162 if (element_Grain->FindElement("iyy")) {
163 Element* element_iyy = element_Grain->FindElement("iyy");
164 if (element_iyy->GetAttributeValue("unit") == "KG*M2") iyy_unit = 1.0/1.35594;
165 if (element_iyy->FindElement("function") != 0) {
166 function_iyy = new FGFunction(exec, element_iyy->FindElement("function"));
167 }
168 } else {
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.");
170 }
171
172 if (element_Grain->FindElement("izz")) {
173 Element* element_izz = element_Grain->FindElement("izz");
174 if (element_izz->GetAttributeValue("unit") == "KG*M2") izz_unit = 1.0/1.35594;
175 if (element_izz->FindElement("function") != 0) {
176 function_izz = new FGFunction(exec, element_izz->FindElement("function"));
177 }
178 } else {
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.");
180 }
181 }
182 else
183 cerr << el->ReadFrom() << "Unknown propellant grain type specified"
184 << endl;
185
186 if (element_Grain->FindElement("length"))
187 Length = element_Grain->FindElementValueAsNumberConvertTo("length", "IN");
188 if (element_Grain->FindElement("bore_diameter"))
189 InnerRadius = element_Grain->FindElementValueAsNumberConvertTo("bore_diameter", "IN")/2.0;
190
191 // Initialize solid propellant values for debug and runtime use.
192
193 switch (grainType) {
194 case gtCYLINDRICAL:
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;
198 throw BaseException(s);
199 }
200 Volume = M_PI * Length * (Radius*Radius - InnerRadius*InnerRadius); // cubic inches
201 break;
202 case gtENDBURNING:
203 Volume = M_PI * Length * Radius * Radius; // cubic inches
204 break;
205 case gtFUNCTION:
206 Volume = 1; // Volume is irrelevant for the FUNCTION type, but it can't be zero!
207 break;
208 case gtUNKNOWN:
209 {
210 const string s("Unknown grain type found in this rocket engine definition.");
211 cerr << el->ReadFrom() << endl << s << endl;
212 throw BaseException(s);
213 }
214 }
215 Density = (Capacity*lbtoslug)/Volume; // slugs/in^3
216 }
217
218 CalculateInertias();
219
220 if (Temperature != -9999.0) InitialTemperature = Temperature = FahrenheitToCelsius(Temperature);
221 Area = 40.0 * pow(Capacity/1975, 0.666666667);
222
223 // A named fuel type will override a previous density value
224 if (!strFuelName.empty()) Density = ProcessFuelName(strFuelName);
225
226 bind(PropertyManager);
227
228 Debug(0);
229}
230
231//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232
234{
235 Debug(1);
236}
237
238//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239
241{
242 SetTemperature( InitialTemperature );
243 SetStandpipe ( InitialStandpipe );
244 SetContents ( InitialContents );
245 PctFull = 100.0*Contents/Capacity;
246 SetPriority( InitialPriority );
247 CalculateInertias();
248}
249
250//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251
253{
254 return vXYZ_drain + (Contents/Capacity)*(vXYZ - vXYZ_drain);
255}
256
257//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258
259double FGTank::GetXYZ(int idx) const
260{
261 return vXYZ_drain(idx) + (Contents/Capacity)*(vXYZ(idx)-vXYZ_drain(idx));
262}
263
264//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265
266double FGTank::Drain(double used)
267{
268 double remaining = Contents - used;
269
270 if (remaining >= GetUnusable()) { // Reduce contents by amount used.
271 Contents -= used;
272 } else { // This tank must be empty.
273 if (Contents > GetUnusable())
274 Contents = GetUnusable();
275
276 remaining = Contents;
277 }
278
279 PctFull = 100.0*Contents/Capacity;
280 CalculateInertias();
281
282 return remaining;
283}
284
285//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286
287double FGTank::Fill(double amount)
288{
289 double overage = 0.0;
290
291 Contents += amount;
292
293 if (Contents > Capacity) {
294 overage = Contents - Capacity;
295 Contents = Capacity;
296 PctFull = 100.0;
297 } else {
298 PctFull = Contents/Capacity*100.0;
299 }
300
301 CalculateInertias();
302
303 return overage;
304}
305
306//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307
308void FGTank::SetContents(double amount)
309{
310 Contents = amount;
311 if (Contents > Capacity) {
312 Contents = Capacity;
313 PctFull = 100.0;
314 } else {
315 PctFull = Contents/Capacity*100.0;
316 }
317
318 CalculateInertias();
319}
320
321//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322
323void FGTank::SetContentsGallons(double gallons)
324{
325 SetContents(gallons * Density);
326}
327
328
329//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330
331double FGTank::Calculate(double dt, double TAT_C)
332{
333 if(ExternalFlow < 0.) Drain( -ExternalFlow *dt);
334 else Fill(ExternalFlow * dt);
335
336 if (Temperature == -9999.0) return 0.0;
337 double HeatCapacity = 900.0; // Joules/lbm/C
338 double TempFlowFactor = 1.115; // Watts/sqft/C
339 double Tdiff = TAT_C - Temperature;
340 double dTemp = 0.0; // Temp change due to one surface
341 if (fabs(Tdiff) > 0.1 && Contents > 0.01) {
342 dTemp = (TempFlowFactor * Area * Tdiff * dt) / (Contents * HeatCapacity);
343 }
344
345 return Temperature += (dTemp + dTemp); // For now, assume upper/lower the same
346}
347
348//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349// This function calculates the moments of inertia for a solid propellant
350// grain - either an end burning cylindrical grain or a bored cylindrical
351// grain, as well as liquid propellants IF a tank radius and inertia factor
352// are given.
353//
354// From NASA CR-383, the MoI of a tank with liquid propellant is specified
355// for baffled and non-baffled tanks as a ratio compared to that in which the
356// propellant is solid. The more baffles, the more "rigid" the propellant and
357// the higher the ratio (up to 1.0). For a cube tank with five baffles, the
358// ratio ranges from 0.5 to 0.7. For a cube tank with no baffles, the ratio is
359// roughly 0.18. One might estimate that for a spherical tank with no baffles
360// the ratio might be somewhere around 0.10 to 0.15. Cylindrical tanks with or
361// without baffles might have biased moment of inertia effects based on the
362// baffle layout and tank geometry. A vector inertia_factor may be supported
363// at some point.
364
365void FGTank::CalculateInertias(void)
366{
367 double Mass = Contents*lbtoslug;
368 double RadSumSqr;
369 double Rad2 = Radius*Radius;
370
371 if (grainType != gtUNKNOWN) { // assume solid propellant
372
373 if (Density > 0.0) {
374 Volume = (Contents*lbtoslug)/Density; // in^3
375 } else if (Contents <= 0.0) {
376 Volume = 0;
377 } else {
378 const string s(" Solid propellant grain density is zero!");
379 cerr << endl << s << endl;
380 throw BaseException(s);
381 }
382
383 switch (grainType) {
384 case gtCYLINDRICAL:
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;
389 Izz = Iyy;
390 break;
391 case gtENDBURNING:
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);
395 Izz = Iyy;
396 break;
397 case gtFUNCTION:
398 Ixx = function_ixx->GetValue()*ixx_unit;
399 Iyy = function_iyy->GetValue()*iyy_unit;
400 Izz = function_izz->GetValue()*izz_unit;
401 break;
402 default:
403 {
404 const string s("Unknown grain type found.");
405 cerr << s << endl;
406 throw BaseException(s);
407 }
408 }
409
410 } else { // assume liquid propellant: shrinking snowball
411
412 if (Radius > 0.0) Ixx = Iyy = Izz = Mass * InertiaFactor * 0.4 * Radius * Radius / 144.0;
413
414 }
415}
416
417//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418
419double FGTank::ProcessFuelName(const std::string& name)
420{
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;
434 //else if (name == "JP-9") return 6.74;
435 //else if (name == "JPTS") return 6.74;
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;
446 else {
447 cerr << "Unknown fuel type specified: "<< name << endl;
448 }
449
450 return 6.6;
451}
452
453//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454
455void FGTank::bind(FGPropertyManager* PropertyManager)
456{
457 string property_name, base_property_name;
458 base_property_name = CreateIndexedPropertyName("propulsion/tank", TankNumber);
459 property_name = base_property_name + "/contents-lbs";
460 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetContents,
462 property_name = base_property_name + "/unusable-volume-gal";
463 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetUnusableVolume,
465 property_name = base_property_name + "/pct-full";
466 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPctFull);
467 property_name = base_property_name + "/density-lbs_per_gal";
468 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetDensity);
469
470 property_name = base_property_name + "/priority";
471 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetPriority,
473 property_name = base_property_name + "/external-flow-rate-pps";
474 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetExternalFlow,
476 property_name = base_property_name + "/local-ixx-slug_ft2";
477 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIxx);
478 property_name = base_property_name + "/local-iyy-slug_ft2";
479 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIyy);
480 property_name = base_property_name + "/local-izz-slug_ft2";
481 PropertyManager->Tie( property_name.c_str(), (FGTank*)this, &FGTank::GetIzz);
482
483 property_name = base_property_name + "/x-position";
484 PropertyManager->Tie(property_name.c_str(), (FGTank*)this, &FGTank::GetLocationX, &FGTank::SetLocationX);
485 property_name = base_property_name + "/y-position";
486 PropertyManager->Tie(property_name.c_str(), (FGTank*)this, &FGTank::GetLocationY, &FGTank::SetLocationY);
487 property_name = base_property_name + "/z-position";
488 PropertyManager->Tie(property_name.c_str(), (FGTank*)this, &FGTank::GetLocationZ, &FGTank::SetLocationZ);
489
490}
491
492//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493// The bitmasked value choices are as follows:
494// unset: In this case (the default) JSBSim would only print
495// out the normally expected messages, essentially echoing
496// the config files as they are read. If the environment
497// variable is not set, debug_lvl is set to 1 internally
498// 0: This requests JSBSim not to output any messages
499// whatsoever.
500// 1: This value explicity requests the normal JSBSim
501// startup messages
502// 2: This value asks for a message to be printed out when
503// a class is instantiated
504// 4: When this value is set, a message is displayed when a
505// FGModel object executes its Run() method
506// 8: When this value is set, various runtime state variables
507// are printed out periodically
508// 16: When set various parameters are sanity checked and
509// a message is printed out when they go out of bounds
510
511void FGTank::Debug(int from)
512{
513 if (debug_lvl <= 0) return;
514
515 if (debug_lvl & 1) { // Standard console startup message output
516 if (from == 0) { // Constructor
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;
523 }
524 }
525 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
526 if (from == 0) cout << "Instantiated: FGTank" << endl;
527 if (from == 1) cout << "Destroyed: FGTank" << endl;
528 }
529 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
530 }
531 if (debug_lvl & 8 ) { // Runtime state variables
532 }
533 if (debug_lvl & 16) { // Sanity checking
534 }
535 if (debug_lvl & 64) {
536 if (from == 0) { // Constructor
537 }
538 }
539}
540}
#define M_PI
Definition FGJSBBase.h:50
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.
Definition FGFunction.h:753
static constexpr double FahrenheitToCelsius(double fahrenheit)
Converts from degrees Fahrenheit to degrees Celsius.
Definition FGJSBBase.h:230
static constexpr double lbtoslug
Definition FGJSBBase.h:367
static short debug_lvl
Definition FGJSBBase.h:190
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.
Models a fuel tank.
Definition FGTank.h:202
void SetContentsGallons(double gallons)
Definition FGTank.cpp:323
double GetPctFull(void) const
Gets the tank fill level.
Definition FGTank.h:248
double GetLocationY(void) const
Definition FGTank.h:301
void SetUnusableVolume(double volume)
Sets the volume of unusable fuel in the tank.
Definition FGTank.h:294
~FGTank()
Destructor.
Definition FGTank.cpp:233
void ResetToIC(void)
Resets the tank parameters to the initial conditions.
Definition FGTank.cpp:240
double GetUnusableVolume(void) const
Returns the unusable volume of fuel in the tank.
Definition FGTank.h:290
double Drain(double used)
Removes fuel from the tank.
Definition FGTank.cpp:266
double GetContents(void) const
Gets the contents of the tank.
Definition FGTank.h:260
double GetLocationZ(void) const
Definition FGTank.h:302
double GetIyy(void) const
Definition FGTank.h:297
void SetExternalFlow(double f)
Definition FGTank.h:320
double GetIxx(void) const
Definition FGTank.h:296
double Calculate(double dt, double TempC)
Performs local, tanks-specific calculations, such as fuel temperature.
Definition FGTank.cpp:331
void SetTemperature(double temp)
Definition FGTank.h:330
void SetLocationX(double x)
Definition FGTank.h:303
void SetPriority(int p)
Definition FGTank.h:310
void SetLocationZ(double z)
Definition FGTank.h:305
double GetLocationX(void) const
Definition FGTank.h:300
void SetLocationY(double y)
Definition FGTank.h:304
void SetStandpipe(double amount)
Definition FGTank.h:331
double GetIzz(void) const
Definition FGTank.h:298
double ProcessFuelName(const std::string &name)
Returns the density of a named fuel type.
Definition FGTank.cpp:419
FGColumnVector3 GetXYZ(void) const
Definition FGTank.cpp:252
int GetPriority(void) const
Definition FGTank.h:309
double Fill(double amount)
Definition FGTank.cpp:287
void SetContents(double amount)
Definition FGTank.cpp:308
double GetUnusable(void) const
Returns the amount of unusable fuel in the tank.
Definition FGTank.h:286
double GetExternalFlow(void) const
Definition FGTank.h:319
double GetDensity(void) const
Returns the fuel density.
Definition FGTank.h:314
FGTank(FGFDMExec *exec, Element *el, int tank_number)
Constructor.
Definition FGTank.cpp:51
const char * name