JSBSim Flight Dynamics Model 1.3.3 (16 Oct 2026)
An Open Source Flight Dynamics and Control Software Library in C++
Loading...
Searching...
No Matches
FGGasCell Class Reference

Detailed Description

Models a gas cell.

Author
Anders Gidenstam

Configuration File Format:

<buoyant_forces>
<gas_cell type="{HYDROGEN | HELIUM | AIR}">
<location unit="{M | IN}">
<x> {number} </x>
<y> {number} </y>
<z> {number} </z>
</location>
<x_width unit="{M | IN}"> {number} </x_width>
<y_radius unit="{M | IN}"> {number} </y_radius>
<z_radius unit="{M | IN}"> {number} </z_radius>
<max_overpressure unit="{PA | PSI}"> {number} </max_overpressure>
<valve_coefficient unit="{M4*SEC/KG | FT4*SEC/SLUG}"> {number} </valve_coefficient>
<fullness> {number} </fullness>
<heat>
{heat transfer coefficients} [lbs ft / sec]
</heat>
<ballonet>
<location unit="{M | IN}">
<x> {number} </x>
<y> {number} </y>
<z> {number} </z>
</location>
<x_width unit="{M | IN}"> {number} </x_width>
<y_radius unit="{M | IN}"> {number} </y_radius>
<z_radius unit="{M | IN}"> {number} </z_radius>
<max_overpressure unit="{PA | PSI}"> {number} </max_overpressure>
<valve_coefficient unit="{M4*SEC/KG | FT4*SEC/SLUG}"> {number} </valve_coefficient>
<fullness> {number} </fullness>
<heat>
{heat transfer coefficients} [lb ft / (sec Rankine)]
</heat>
<blower_input>
{input air flow function} [ft^3 / sec]
</blower_input>
</ballonet>
</gas_cell>
</buoyant_forces>

Definition of the gas cell configuration file parameters:

  • type - One of HYDROGEN, HELIUM or AIR.
  • location - Location of cell center in the aircraft's structural frame. Currently this is were the forces of the cell is applied.
  • {x|y|z}_radius - Radius along in the respective direction (both ends).
  • {x|y|z}_width - Width in the respective direction. NOTE: A 'x', 'y', 'z'-radius/width combination must be specified.
  • fullness - Initial fullness of the cell, normally [0,1], values >1 initialize the cell at pressure.
  • max_overpressure - Maximum cell overpressure (excess is automatically valved off).
  • valve_coefficient - Capacity of the manual valve. The valve is considered to be located at the top of the cell. The valve coefficient determine the flow out of the cell according to: dVolume/dt = ValveCoefficient * DeltaPressure.
  • heat - Zero or more FGFunction:s describing the heat flow from the atmosphere into the gas cell. Unit: [lb ft / (sec Rankine)]. If there are no heat transfer functions at all the gas cell temperature will equal that of the surrounding atmosphere. A constant function returning 0 results in adiabatic behaviour.
  • ballonet - Zero or more ballonets, i.e. air bags inside the gas cell. Ballonets are used to maintain the volume of the gas cell and keep its internal pressure higher than that of the surrounding environment.
    • location - Location of ballonet center in the aircraft's structural frame.
    • {x|y|z}_radius - Radius along in the respective direction (both ends).
    • {x|y|z}_width - Width in the respective direction.
    • max_overpressure - Maximum ballonet overpressure (excess is automatically valved off).
    • valve_coefficient - Capacity of the exit valve between the ballonet and the atmosphere. The valve coefficient determine the flow out of the cell according to: dVolume/dt = ValveCoefficient * DeltaPressure.
    • heat - Zero or more FGFunction:s describing the heat flow from the enclosing gas cell into the ballonet. Unit: [lb ft / (sec Rankine)]
    • blower_input - One FGFunction describing the air flow into the ballonet. Unit: [ft3 / sec] (at the temperature and pressure of the ballonet.)

Definition at line 166 of file FGGasCell.h.

#include <FGGasCell.h>

+ Inheritance diagram for FGGasCell:
+ Collaboration diagram for FGGasCell:

Classes

struct  Inputs
 

Public Member Functions

 FGGasCell (FGFDMExec *exec, Element *el, unsigned int num, const struct Inputs &input)
 Constructor.
 
void Calculate (double dt)
 Runs the gas cell model; called by BuoyantForces.
 
int GetIndex (void) const
 Get the index of this gas cell.
 
const FGMatrix33 & GetInertia (void) const
 Get the moments of inertia of the gas cell (including any ballonets)
 
double GetMass (void) const
 Get the current mass of the gas cell (including any ballonets)
 
const FGColumnVector3 & GetMassMoment (void) const
 Get the moment due to mass of the gas cell (including any ballonets)
 
double GetPressure (void) const
 Get the current gas pressure inside the gas cell.
 
double GetTemperature (void) const
 Get the current gas temperature inside the gas cell.
 
double GetXYZ (int idx) const
 Get the center of gravity location of the gas cell (including any ballonets)
 
const FGColumnVector3 & GetXYZ (void) const
 Get the center of gravity location of the gas cell (including any ballonets)
 
- Public Member Functions inherited from FGForce
 FGForce (FGFDMExec *FDMExec)
 Constructor.
 
virtual ~FGForce ()
 Destructor.
 
const FGColumnVector3 & GetActingLocation (void) const
 
double GetActingLocationX (void) const
 
double GetActingLocationY (void) const
 
double GetActingLocationZ (void) const
 
double GetAnglesToBody (int axis) const
 
const FGColumnVector3 & GetAnglesToBody (void) const
 
virtual const FGColumnVector3 & GetBodyForces (void)
 
double GetBodyXForce (void) const
 
double GetBodyYForce (void) const
 
double GetBodyZForce (void) const
 
const FGColumnVector3 & GetLocation (void) const
 
double GetLocationX (void) const
 
double GetLocationY (void) const
 
double GetLocationZ (void) const
 
const FGColumnVector3 & GetMoments (void) const
 
double GetPitch (void) const
 
TransformType GetTransformType (void) const
 
double GetYaw (void) const
 
void SetActingLocation (const FGColumnVector3 &vv)
 
void SetActingLocation (double x, double y, double z)
 Acting point of application.
 
void SetActingLocationX (double x)
 
void SetActingLocationY (double y)
 
void SetActingLocationZ (double z)
 
void SetAnglesToBody (const FGColumnVector3 &vv)
 
void SetAnglesToBody (double broll, double bpitch, double byaw)
 
void SetLocation (const FGColumnVector3 &vv)
 
void SetLocation (double x, double y, double z)
 
void SetLocationX (double x)
 
void SetLocationY (double y)
 
void SetLocationZ (double z)
 
void SetPitch (double pitch)
 
void SetTransformType (TransformType ii)
 
void SetYaw (double yaw)
 
const FGMatrix33 & Transform (void) const
 
void UpdateCustomTransformMatrix (void)
 
- Public Member Functions inherited from FGJSBBase
 FGJSBBase ()
 Constructor for FGJSBBase.
 
virtual ~FGJSBBase ()
 Destructor for FGJSBBase.
 

Public Attributes

const struct Inputs & in
 

Additional Inherited Members

- Public Types inherited from FGForce
enum  TransformType {
  tNone , tWindBody , tLocalBody , tInertialBody ,
  tCustom
}
 
- Public Types inherited from FGJSBBase
enum  { eL = 1 , eM , eN }
 Moments L, M, N. More...
 
enum  { eP = 1 , eQ , eR }
 Rates P, Q, R. More...
 
enum  { eU = 1 , eV , eW }
 Velocities U, V, W. More...
 
enum  { eX = 1 , eY , eZ }
 Positions X, Y, Z. More...
 
enum  { ePhi = 1 , eTht , ePsi }
 Euler angles Phi, Theta, Psi. More...
 
enum  { eDrag = 1 , eSide , eLift }
 Stability axis forces, Drag, Side force, Lift. More...
 
enum  { eRoll = 1 , ePitch , eYaw }
 Local frame orientation Roll, Pitch, Yaw. More...
 
enum  { eNorth = 1 , eEast , eDown }
 Local frame position North, East, Down. More...
 
enum  { eLat = 1 , eLong , eRad }
 Locations Radius, Latitude, Longitude. More...
 
enum  {
  inNone = 0 , inDegrees , inRadians , inMeters ,
  inFeet
}
 Conversion specifiers. More...
 
- Static Public Member Functions inherited from FGJSBBase
static constexpr double CelsiusToFahrenheit (double celsius)
 Converts from degrees Celsius to degrees Fahrenheit.
 
static constexpr double CelsiusToKelvin (double celsius)
 Converts from degrees Celsius to degrees Kelvin.
 
static constexpr double CelsiusToRankine (double celsius)
 Converts from degrees Celsius to degrees Rankine.
 
static constexpr double Constrain (double min, double value, double max)
 Constrain a value between a minimum and a maximum value.
 
static bool EqualToRoundoff (double a, double b)
 Finite precision comparison.
 
static bool EqualToRoundoff (double a, float b)
 Finite precision comparison.
 
static bool EqualToRoundoff (float a, double b)
 Finite precision comparison.
 
static bool EqualToRoundoff (float a, float b)
 Finite precision comparison.
 
static constexpr double FahrenheitToCelsius (double fahrenheit)
 Converts from degrees Fahrenheit to degrees Celsius.
 
static constexpr double FeetToMeters (double measure)
 Converts from feet to meters.
 
static const std::string & GetVersion (void)
 Returns the version number of JSBSim.
 
static constexpr double KelvinToCelsius (double kelvin)
 Converts from degrees Kelvin to degrees Celsius.
 
static constexpr double KelvinToFahrenheit (double kelvin)
 Converts from degrees Kelvin to degrees Fahrenheit.
 
static constexpr double KelvinToRankine (double kelvin)
 Converts from degrees Kelvin to degrees Rankine.
 
static constexpr double RankineToCelsius (double rankine)
 Converts from degrees Rankine to degrees Celsius.
 
static constexpr double RankineToKelvin (double rankine)
 Converts from degrees Rankine to degrees Kelvin.
 
static constexpr double sign (double num)
 
- Static Public Attributes inherited from FGJSBBase
static short debug_lvl = 1
 
- Static Protected Member Functions inherited from FGJSBBase
static std::string CreateIndexedPropertyName (const std::string &Property, int index)
 
- Protected Attributes inherited from FGForce
FGFDMExec * fdmex
 
std::shared_ptr< FGMassBalance > MassBalance
 
FGMatrix33 mT
 
TransformType ttype
 
FGColumnVector3 vActingXYZn
 
FGColumnVector3 vFn
 
FGColumnVector3 vMn
 
FGColumnVector3 vOrient
 
FGColumnVector3 vXYZn
 
- Static Protected Attributes inherited from FGJSBBase
static constexpr double degtorad = M_PI / 180.
 
static constexpr double fpstokts = 1.0 / ktstofps
 
static constexpr double fttom = 0.3048
 
static constexpr double hptoftlbssec = 550.0
 
static constexpr double in3tom3 = inchtoft*inchtoft*inchtoft/m3toft3
 
static constexpr double inchtoft = 1.0/12.0
 
static constexpr double inhgtopa = 3386.38
 
static const std::string JSBSim_version = JSBSIM_VERSION " " __DATE__ " " __TIME__
 
static constexpr double kgtolb = 2.20462
 
static constexpr double kgtoslug = 0.06852168
 
static constexpr double ktstofps = 1852./(3600*fttom)
 
static constexpr double lbtoslug = 1.0/slugtolb
 
static constexpr double m3toft3 = 1.0/(fttom*fttom*fttom)
 
static const std::string needed_cfg_version = "2.0"
 
static constexpr double psftoinhg = 0.014138
 
static constexpr double psftopa = 47.88
 
static constexpr double radtodeg = 180. / M_PI
 
static constexpr double slugtolb = 32.174049
 Note that definition of lbtoslug by the inverse of slugtolb and not to a different constant you can also get from some tables will make lbtoslug*slugtolb == 1 up to the magnitude of roundoff.
 

Constructor & Destructor Documentation

◆ FGGasCell()

FGGasCell ( FGFDMExec *  exec,
Element *  el,
unsigned int  num,
const struct Inputs &  input 
)

Constructor.

Parameters
execExecutive a pointer to the parent executive object
elPointer to configuration file XML node
numGas cell index number.

Definition at line 59 of file FGGasCell.cpp.

61 : FGForce(exec), in(input)
62{
63 string token;
64 Element* element;
65
66 auto PropertyManager = exec->GetPropertyManager();
67 MassBalance = exec->GetMassBalance();
68
69 Buoyancy = MaxVolume = MaxOverpressure = Temperature = Pressure =
70 Contents = Volume = dVolumeIdeal = 0.0;
71 Xradius = Yradius = Zradius = Xwidth = Ywidth = Zwidth = 0.0;
72 ValveCoefficient = ValveOpen = 0.0;
73 CellNum = num;
74
75 // NOTE: In the local system X points north, Y points east and Z points down.
76 SetTransformType(FGForce::tLocalBody);
77
78 type = el->GetAttributeValue("type");
79 if (type == "HYDROGEN") Type = ttHYDROGEN;
80 else if (type == "HELIUM") Type = ttHELIUM;
81 else if (type == "AIR") Type = ttAIR;
82 else Type = ttUNKNOWN;
83
84 element = el->FindElement("location");
85 if (element) {
86 vXYZ = element->FindElementTripletConvertTo("IN");
87 } else {
88 XMLLogException err(el);
89 err << "\nFatal Error: No location found for this gas cell.\n";
90 throw err;
91 }
92 if ((el->FindElement("x_radius") || el->FindElement("x_width")) &&
93 (el->FindElement("y_radius") || el->FindElement("y_width")) &&
94 (el->FindElement("z_radius") || el->FindElement("z_width"))) {
95
96 if (el->FindElement("x_radius")) {
97 Xradius = el->FindElementValueAsNumberConvertTo("x_radius", "FT");
98 }
99 if (el->FindElement("y_radius")) {
100 Yradius = el->FindElementValueAsNumberConvertTo("y_radius", "FT");
101 }
102 if (el->FindElement("z_radius")) {
103 Zradius = el->FindElementValueAsNumberConvertTo("z_radius", "FT");
104 }
105
106 if (el->FindElement("x_width")) {
107 Xwidth = el->FindElementValueAsNumberConvertTo("x_width", "FT");
108 }
109 if (el->FindElement("y_width")) {
110 Ywidth = el->FindElementValueAsNumberConvertTo("y_width", "FT");
111 }
112 if (el->FindElement("z_width")) {
113 Zwidth = el->FindElementValueAsNumberConvertTo("z_width", "FT");
114 }
115
116 // The volume is a (potentially) extruded ellipsoid.
117 // However, currently only a few combinations of radius and width are
118 // fully supported.
119 if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
120 (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) {
121 // Ellipsoid volume.
122 MaxVolume = 4.0 * M_PI * Xradius * Yradius * Zradius / 3.0;
123 } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
124 (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) {
125 // Cylindrical volume.
126 MaxVolume = M_PI * Yradius * Zradius * Xwidth;
127 } else {
128 FGXMLLogging log(el, LogLevel::WARN);
129 log << "Unsupported gas cell shape.\n";
130 MaxVolume =
131 (4.0 * M_PI * Xradius * Yradius * Zradius / 3.0 +
132 M_PI * Yradius * Zradius * Xwidth +
133 M_PI * Xradius * Zradius * Ywidth +
134 M_PI * Xradius * Yradius * Zwidth +
135 2.0 * Xradius * Ywidth * Zwidth +
136 2.0 * Yradius * Xwidth * Zwidth +
137 2.0 * Zradius * Xwidth * Ywidth +
138 Xwidth * Ywidth * Zwidth);
139 }
140 } else {
141 XMLLogException err(el);
142 err << "\nGas cell shape must be given.\n";
143 throw err;
144 }
145 if (el->FindElement("max_overpressure")) {
146 MaxOverpressure = el->FindElementValueAsNumberConvertTo("max_overpressure",
147 "LBS/FT2");
148 }
149 if (el->FindElement("fullness")) {
150 const double Fullness = el->FindElementValueAsNumber("fullness");
151 if (0 <= Fullness) {
152 Volume = Fullness * MaxVolume;
153 } else {
154 FGXMLLogging log(el, LogLevel::WARN);
155 log << "Invalid initial gas cell fullness value.\n";
156 }
157 }
158 if (el->FindElement("valve_coefficient")) {
159 ValveCoefficient =
160 el->FindElementValueAsNumberConvertTo("valve_coefficient",
161 "FT4*SEC/SLUG");
162 ValveCoefficient = max(ValveCoefficient, 0.0);
163 }
164
165 // Initialize state
166 SetLocation(vXYZ);
167
168 if (Temperature == 0.0) {
169 Temperature = in.Temperature;
170 }
171 if (Pressure == 0.0) {
172 Pressure = in.Pressure;
173 }
174 if (Volume != 0.0) {
175 // Calculate initial gas content.
176 Contents = Pressure * Volume / (R * Temperature);
177
178 // Clip to max allowed value.
179 const double IdealPressure = Contents * R * Temperature / MaxVolume;
180 if (IdealPressure > Pressure + MaxOverpressure) {
181 Contents = (Pressure + MaxOverpressure) * MaxVolume / (R * Temperature);
182 Pressure = Pressure + MaxOverpressure;
183 } else {
184 Pressure = max(IdealPressure, Pressure);
185 }
186 } else {
187 // Calculate initial gas content.
188 Contents = Pressure * MaxVolume / (R * Temperature);
189 }
190
191 Volume = Contents * R * Temperature / Pressure;
192 Mass = Contents * M_gas();
193
194 // Bind relevant properties
195 string property_name, base_property_name;
196
197 base_property_name = CreateIndexedPropertyName("buoyant_forces/gas-cell", CellNum);
198
199 property_name = base_property_name + "/max_volume-ft3";
200 PropertyManager->Tie( property_name.c_str(), &MaxVolume);
201 PropertyManager->GetNode(property_name)->setAttribute( SGPropertyNode::WRITE, false );
202 property_name = base_property_name + "/temp-R";
203 PropertyManager->Tie( property_name.c_str(), &Temperature);
204 property_name = base_property_name + "/pressure-psf";
205 PropertyManager->Tie( property_name.c_str(), &Pressure);
206 property_name = base_property_name + "/volume-ft3";
207 PropertyManager->Tie( property_name.c_str(), &Volume);
208 property_name = base_property_name + "/buoyancy-lbs";
209 PropertyManager->Tie( property_name.c_str(), &Buoyancy);
210 property_name = base_property_name + "/contents-mol";
211 PropertyManager->Tie( property_name.c_str(), &Contents);
212 property_name = base_property_name + "/valve_open";
213 PropertyManager->Tie( property_name.c_str(), &ValveOpen);
214
215 Debug(0);
216
217 // Read heat transfer coefficients
218 if (Element* heat = el->FindElement("heat")) {
219 Element* function_element = heat->FindElement("function");
220 while (function_element) {
221 HeatTransferCoeff.push_back(new FGFunction(exec, function_element));
222 function_element = heat->FindNextElement("function");
223 }
224 }
225
226 // Load ballonets if there are any
227 if (Element* ballonet_element = el->FindElement("ballonet")) {
228 while (ballonet_element) {
229 Ballonet.push_back(new FGBallonet(exec,
230 ballonet_element,
231 Ballonet.size(),
232 this, in));
233 ballonet_element = el->FindNextElement("ballonet");
234 }
235 }
236
237}
FGForce(FGFDMExec *FDMExec)
Constructor.
Definition FGForce.cpp:53
+ Here is the call graph for this function:

◆ ~FGGasCell()

~FGGasCell ( )

Definition at line 241 of file FGGasCell.cpp.

242{
243 unsigned int i;
244
245 for (i = 0; i < HeatTransferCoeff.size(); i++) delete HeatTransferCoeff[i];
246 HeatTransferCoeff.clear();
247
248 for (i = 0; i < Ballonet.size(); i++) delete Ballonet[i];
249 Ballonet.clear();
250
251 Debug(1);
252}

Member Function Documentation

◆ Calculate()

void Calculate ( double  dt)

Runs the gas cell model; called by BuoyantForces.

Definition at line 256 of file FGGasCell.cpp.

257{
258 const double AirTemperature = in.Temperature; // [Rankine]
259 const double AirPressure = in.Pressure; // [lbs/ft^2]
260 const double AirDensity = in.Density; // [slug/ft^3]
261 const double g = in.gravity; // [lbs/slug]
262
263 const double OldTemperature = Temperature;
264 const double OldPressure = Pressure;
265 unsigned int i;
266 const size_t no_ballonets = Ballonet.size();
267
268 //-- Read ballonet state --
269 // NOTE: This model might need a more proper integration technique.
270 double BallonetsVolume = 0.0;
271 double BallonetsHeatFlow = 0.0;
272 for (i = 0; i < no_ballonets; i++) {
273 BallonetsVolume += Ballonet[i]->GetVolume();
274 BallonetsHeatFlow += Ballonet[i]->GetHeatFlow();
275 }
276
277 //-- Gas temperature --
278
279 if (!HeatTransferCoeff.empty()) {
280 // The model is based on the ideal gas law.
281 // However, it does look a bit fishy. Please verify.
282 // dT/dt = dU / (Cv n R)
283 double dU = 0.0;
284 for (i = 0; i < HeatTransferCoeff.size(); i++) {
285 dU += HeatTransferCoeff[i]->GetValue();
286 }
287 // Don't include dt when accounting for adiabatic expansion/contraction.
288 // The rate of adiabatic cooling looks about right: ~5.4 Rankine/1000ft.
289 if (Contents > 0) {
290 Temperature +=
291 (dU * dt - Pressure * dVolumeIdeal - BallonetsHeatFlow) /
292 (Cv_gas() * Contents * R);
293 } else {
294 Temperature = AirTemperature;
295 }
296 } else {
297 // No simulation of complex temperature changes.
298 // Note: Making the gas cell behave adiabatically might be a better
299 // option.
300 Temperature = AirTemperature;
301 }
302
303 //-- Pressure --
304 const double IdealPressure =
305 Contents * R * Temperature / (MaxVolume - BallonetsVolume);
306 if (IdealPressure > AirPressure + MaxOverpressure) {
307 Pressure = AirPressure + MaxOverpressure;
308 } else {
309 Pressure = max(IdealPressure, AirPressure);
310 }
311
312 //-- Manual valving --
313
314 // FIXME: Presently the effect of manual valving is computed using
315 // an ad hoc formula which might not be a good representation
316 // of reality.
317 if ((ValveCoefficient > 0.0) && (ValveOpen > 0.0)) {
318 // Scale CellHeight by the ratio of current gas volume to maximum
319 // volume so that as the cell deflates, the buoyancy-driven pressure
320 // differential diminishes naturally toward zero.
321 const double GasVolume = Contents * R * Temperature / Pressure; // [ft^3]
322 const double CellHeight = (2 * Zradius + Zwidth) *
323 min(1.0, GasVolume / MaxVolume); // [ft]
324 const double GasDensity = M_gas() * Pressure / (R * Temperature);
325 const double DeltaPressure = max(0.0,
326 Pressure + CellHeight * g * (AirDensity - GasDensity) - AirPressure);
327 const double VolumeValved =
328 ValveOpen * ValveCoefficient * DeltaPressure * dt;
329 Contents =
330 max(0.0, Contents - Pressure * VolumeValved / (R * Temperature));
331 }
332
333 //-- Update ballonets. --
334 // Doing that here should give them the opportunity to react to the
335 // new pressure.
336 BallonetsVolume = 0.0;
337 for (i = 0; i < no_ballonets; i++) {
338 Ballonet[i]->Calculate(dt);
339 BallonetsVolume += Ballonet[i]->GetVolume();
340 }
341
342 //-- Automatic safety valving. --
343 if (Contents * R * Temperature / (MaxVolume - BallonetsVolume) >
344 AirPressure + MaxOverpressure) {
345 // Gas is automatically valved. Valving capacity is assumed to be infinite.
346 // FIXME: This could/should be replaced by damage to the gas cell envelope.
347 Contents =
348 (AirPressure + MaxOverpressure) *
349 (MaxVolume - BallonetsVolume) / (R * Temperature);
350 }
351
352 //-- Volume --
353 Volume = Contents * R * Temperature / Pressure + BallonetsVolume;
354 dVolumeIdeal =
355 Contents * R * (Temperature / Pressure - OldTemperature / OldPressure);
356
357 //-- Current buoyancy --
358 // The buoyancy is computed using the atmospheres local density.
359 Buoyancy = Volume * AirDensity * g;
360
361 // Note: This is gross buoyancy. The weight of the gas itself and
362 // any ballonets is not deducted here as the effects of the gas mass
363 // is handled by FGMassBalance.
364 vFn = {0.0, 0.0, - Buoyancy};
365
366 // Compute the inertia of the gas cell.
367 // Consider the gas cell as a shape of uniform density.
368 // FIXME: If the cell isn't ellipsoid or cylindrical the inertia will
369 // be wrong.
370 gasCellJ.InitMatrix();
371 const double mass = Contents * M_gas();
372 double Ixx, Iyy, Izz;
373 if ((Xradius != 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
374 (Xwidth == 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) {
375 // Ellipsoid volume.
376 Ixx = (1.0 / 5.0) * mass * (Yradius*Yradius + Zradius*Zradius);
377 Iyy = (1.0 / 5.0) * mass * (Xradius*Xradius + Zradius*Zradius);
378 Izz = (1.0 / 5.0) * mass * (Xradius*Xradius + Yradius*Yradius);
379 } else if ((Xradius == 0.0) && (Yradius != 0.0) && (Zradius != 0.0) &&
380 (Xwidth != 0.0) && (Ywidth == 0.0) && (Zwidth == 0.0)) {
381 // Cylindrical volume (might not be valid with an elliptical cross-section).
382 Ixx = (1.0 / 2.0) * mass * Yradius * Zradius;
383 Iyy =
384 (1.0 / 4.0) * mass * Yradius * Zradius +
385 (1.0 / 12.0) * mass * Xwidth * Xwidth;
386 Izz =
387 (1.0 / 4.0) * mass * Yradius * Zradius +
388 (1.0 / 12.0) * mass * Xwidth * Xwidth;
389 } else {
390 // Not supported. Revert to pointmass model.
391 Ixx = Iyy = Izz = 0.0;
392 }
393 // The volume is symmetric, so Ixy = Ixz = Iyz = 0.
394 gasCellJ(1,1) = Ixx;
395 gasCellJ(2,2) = Iyy;
396 gasCellJ(3,3) = Izz;
397 Mass = mass;
398 // Transform the moments of inertia to the body frame.
399 gasCellJ += MassBalance->GetPointmassInertia(Mass, GetXYZ());
400
401 gasCellM.InitMatrix();
402 gasCellM(eX) +=
403 GetXYZ(eX) * Mass*slugtolb;
404 gasCellM(eY) +=
405 GetXYZ(eY) * Mass*slugtolb;
406 gasCellM(eZ) +=
407 GetXYZ(eZ) * Mass*slugtolb;
408
409 if (no_ballonets > 0) {
410 // Add the mass, moment and inertia of any ballonets.
411 for (i = 0; i < no_ballonets; i++) {
412 Mass += Ballonet[i]->GetMass();
413
414 // Add ballonet moments due to mass (in the structural frame).
415 gasCellM(eX) +=
416 Ballonet[i]->GetXYZ(eX) * Ballonet[i]->GetMass()*slugtolb;
417 gasCellM(eY) +=
418 Ballonet[i]->GetXYZ(eY) * Ballonet[i]->GetMass()*slugtolb;
419 gasCellM(eZ) +=
420 Ballonet[i]->GetXYZ(eZ) * Ballonet[i]->GetMass()*slugtolb;
421
422 gasCellJ += Ballonet[i]->GetInertia();
423 }
424 }
425}
const FGColumnVector3 & GetXYZ(void) const
Get the center of gravity location of the gas cell (including any ballonets)
Definition FGGasCell.h:195
static constexpr double slugtolb
Note that definition of lbtoslug by the inverse of slugtolb and not to a different constant you can a...
Definition FGJSBBase.h:283
void InitMatrix(void)
Initialize the matrix.
+ Here is the call graph for this function:

◆ GetIndex()

int GetIndex ( void  ) const
inline

Get the index of this gas cell.

Returns
gas cell index.

Definition at line 190 of file FGGasCell.h.

190{return CellNum;}

◆ GetInertia()

const FGMatrix33 & GetInertia ( void  ) const
inline

Get the moments of inertia of the gas cell (including any ballonets)

Returns
moments of inertia matrix in the body frame in slug ft2.

Definition at line 209 of file FGGasCell.h.

209{return gasCellJ;}

◆ GetMass()

double GetMass ( void  ) const
inline

Get the current mass of the gas cell (including any ballonets)

Returns
gas mass in slug.

Definition at line 204 of file FGGasCell.h.

204{return Mass;}

◆ GetMassMoment()

const FGColumnVector3 & GetMassMoment ( void  ) const
inline

Get the moment due to mass of the gas cell (including any ballonets)

Note that the buoyancy of the gas cell is handled separately by the FGForce part and not included here.

Returns
moment vector in the structural frame in lbs in.

Definition at line 216 of file FGGasCell.h.

216{return gasCellM;}

◆ GetPressure()

double GetPressure ( void  ) const
inline

Get the current gas pressure inside the gas cell.

Returns
gas pressure in lbs / ft2.

Definition at line 224 of file FGGasCell.h.

224{return Pressure;}
+ Here is the caller graph for this function:

◆ GetTemperature()

double GetTemperature ( void  ) const
inline

Get the current gas temperature inside the gas cell.

Returns
gas temperature in Rankine.

Definition at line 220 of file FGGasCell.h.

220{return Temperature;}
+ Here is the caller graph for this function:

◆ GetXYZ() [1/2]

double GetXYZ ( int  idx) const
inline

Get the center of gravity location of the gas cell (including any ballonets)

Returns
CoG location in the structural frame in inches.

Definition at line 200 of file FGGasCell.h.

200{return vXYZ(idx);}

◆ GetXYZ() [2/2]

const FGColumnVector3 & GetXYZ ( void  ) const
inline

Get the center of gravity location of the gas cell (including any ballonets)

Returns
CoG location in the structural frame in inches.

Definition at line 195 of file FGGasCell.h.

195{return vXYZ;}
+ Here is the caller graph for this function:

Member Data Documentation

◆ in

const struct Inputs& in

Definition at line 226 of file FGGasCell.h.


The documentation for this class was generated from the following files: