1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4 Author: Anders Gidenstam
5 Date started: 01/21/2006
7 ----- Copyright (C) 2006 - 2008 Anders Gidenstam (anders(at)gidenstam.org) --
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU Lesser General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA.
23 Further information about the GNU Lesser General Public License can also be found on
24 the world wide web at http://www.gnu.org.
26 FUNCTIONAL DESCRIPTION
27 --------------------------------------------------------------------------------
29 This class simulates a generic gas cell for static buoyancy.
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
42 #include <FGJSBBase.h>
43 #include <input_output/FGXMLElement.h>
44 #include <math/FGColumnVector3.h>
45 #include <models/propulsion/FGForce.h>
46 #include <math/FGFunction.h>
54 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
58 #define ID_GASCELL "$Id$"
60 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
68 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
72 /** Models a gas cell.
73 @author Anders Gidenstam
75 <h3>Configuration File Format:</h3>
78 <gas_cell type="{HYDROGEN | HELIUM | AIR}">
79 <location unit="{M | IN}">
84 <x_width unit="{M | IN}"> {number} </x_width>
85 <y_radius unit="{M | IN}"> {number} </y_radius>
86 <z_radius unit="{M | IN}"> {number} </z_radius>
87 <max_overpressure unit="{PA | PSI}"> {number} </max_overpressure>
88 <valve_coefficient unit="{M4*SEC/KG | FT4*SEC/SLUG}"> {number} </valve_coefficient>
89 <fullness> {number} </fullness>
91 {heat transfer coefficients} [lbs ft / sec]
94 <location unit="{M | IN}">
99 <x_width unit="{M | IN}"> {number} </x_width>
100 <y_radius unit="{M | IN}"> {number} </y_radius>
101 <z_radius unit="{M | IN}"> {number} </z_radius>
102 <max_overpressure unit="{PA | PSI}"> {number} </max_overpressure>
103 <valve_coefficient unit="{M4*SEC/KG | FT4*SEC/SLUG}"> {number} </valve_coefficient>
104 <fullness> {number} </fullness>
106 {heat transfer coefficients} [lb ft / (sec Rankine)]
109 {input air flow function} [ft^3 / sec]
116 Definition of the gas cell configuration file parameters:
118 One of HYDROGEN, HELIUM or AIR.
120 Location of cell center in the aircraft's structural frame.
121 Currently this is were the forces of the cell is applied.
122 - <b>{x|y|z}_radius</b> -
123 Radius along in the respective direction (both ends).
124 - <b>{x|y|z}_width</b> -
125 Width in the respective direction.
126 <b>NOTE:</b> A 'x', 'y', 'z'-radius/width combination must be specified.
128 Initial fullness of the cell, normally [0,1],
129 values >1 initialize the cell at pressure.
130 - <b>max_overpressure</b> -
131 Maximum cell overpressure (excess is automatically valved off).
132 - <b>valve_coefficient</b> -
133 Capacity of the manual valve. The valve is
134 considered to be located at the top of the cell.
135 The valve coefficient determine the flow out
136 of the cell according to:
137 <i>dVolume/dt = ValveCoefficient * DeltaPressure</i>.
139 Zero or more FGFunction:s describing the heat flow from
140 the atmosphere into the gas cell.
141 Unit: [lb ft / (sec Rankine)].
142 If there are no heat transfer functions at all the gas cell
143 temperature will equal that of the surrounding atmosphere.
144 A constant function returning 0 results in adiabatic behaviour.
146 Zero or more ballonets, i.e. air bags inside the gas cell.
147 Ballonets are used to maintain the volume of the gas cell
148 and keep its internal pressure higher than that of the
149 surrounding environment.
151 Location of ballonet center in the aircraft's structural frame.
152 - <b>{x|y|z}_radius</b> -
153 Radius along in the respective direction (both ends).
154 - <b>{x|y|z}_width</b> -
155 Width in the respective direction.
156 - <b>max_overpressure</b> -
157 Maximum ballonet overpressure (excess is automatically valved off).
158 - <b>valve_coefficient</b> -
159 Capacity of the exit valve between the ballonet
160 and the atmosphere. The valve coefficient
161 determine the flow out of the cell according to:
162 <i>dVolume/dt = ValveCoefficient * DeltaPressure</i>.
164 Zero or more FGFunction:s describing the heat flow from
165 the enclosing gas cell into the ballonet.
166 Unit: [lb ft / (sec Rankine)]
167 - <b>blower_input</b> -
168 One FGFunction describing the air flow into the
169 ballonet. Unit: [ft<sup>3</sup> / sec] (at the temperature and
170 pressure of the ballonet.)
173 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
176 class FGGasCell : public FGForce
180 @param exec Executive a pointer to the parent executive object
181 @param el Pointer to configuration file XML node
182 @param num Gas cell index number. */
183 FGGasCell(FGFDMExec* exec, Element* el, int num);
186 /** Runs the gas cell model; called by BuoyantForces
188 void Calculate(double dt);
190 /** Get the index of this gas cell
191 @return gas cell index. */
192 int GetIndex(void) {return CellNum;}
194 /** Get the center of gravity location of the gas cell
195 (including any ballonets)
196 @return CoG location in the structural frame. */
197 const FGColumnVector3& GetXYZ(void) {return vXYZ;}
199 /** Get the center of gravity location of the gas cell
200 (including any ballonets)
201 @return CoG location in the structural frame. */
202 double GetXYZ(int idx) {return vXYZ(idx);}
204 /** Get the current mass of the gas cell (including any ballonets)
205 @return gas mass in slug. */
206 double GetMass(void) {return Mass;}
208 /** Get the moments of inertia of the gas cell (including any ballonets)
209 @return moments of inertia matrix in slug ft<sup>2</sup>. */
210 FGMatrix33& GetInertia(void) {return gasCellJ;}
212 /** Get the moment due to mass of the gas cell (including any ballonets)
214 Note that the buoyancy of the gas cell is handled separately by the
215 FGForce part and not included here.
216 @return moment vector in lbs ft. */
217 FGColumnVector3& GetMassMoment(void) {return gasCellM;}
219 /** Get the current gas temperature inside the gas cell
220 @return gas temperature in Rankine. */
221 double GetTemperature(void) {return Temperature;}
223 /** Get the current gas pressure inside the gas cell
224 @return gas pressure in lbs / ft<sup>2</sup>. */
225 double GetPressure(void) {return Pressure;}
229 enum GasType {ttUNKNOWN, ttHYDROGEN, ttHELIUM, ttAIR};
234 // Structural constants
235 double MaxVolume; // [ft�]
236 double MaxOverpressure; // [lbs/ft�]
237 FGColumnVector3 vXYZ; // [in]
238 double Xradius, Yradius, Zradius; // [ft]
239 double Xwidth, Ywidth, Zwidth; // [ft]
240 double ValveCoefficient; // [ft^4 sec / slug]
241 typedef vector <FGFunction*> CoeffArray;
242 CoeffArray HeatTransferCoeff;
243 typedef vector <FGBallonet*> BallonetArray;
244 BallonetArray Ballonet;
246 double Pressure; // [lbs/ft�]
247 double Contents; // [mol]
248 double Volume; // [ft�]
249 double dVolumeIdeal; // [ft�]
250 double Temperature; // [Rankine]
251 double Buoyancy; // [lbs] Note: Gross lift.
252 // Does not include the weight of the gas itself.
253 double ValveOpen; // 0 <= ValveOpen <= 1 (or higher).
254 double Mass; // [slug]
255 FGMatrix33 gasCellJ; // [slug foot�]
256 FGColumnVector3 gasCellM; // [lbs ft]
258 FGAuxiliary* Auxiliary;
259 FGAtmosphere* Atmosphere;
260 FGPropertyManager* PropertyManager;
261 FGInertial* Inertial;
262 FGMassBalance* MassBalance;
263 void Debug(int from);
266 const static double R; // [lbs ft/(mol Rankine)]
267 const static double M_air; // [slug/mol]
268 const static double M_hydrogen; // [slug/mol]
269 const static double M_helium; // [slug/mol]
271 double M_gas() { // [slug/mol]
284 double Cv_gas() { // [??]
299 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 /** Models a ballonet inside a gas cell.
301 Models a ballonet inside a gas cell.
302 Not intended to be used outside FGGasCell.
303 See FGGasCell for the configuration file format.
304 @author Anders Gidenstam
306 class FGBallonet : public FGJSBBase
309 FGBallonet(FGFDMExec* exec, Element* el, int num, FGGasCell* parent);
312 /** Runs the ballonet model; called by FGGasCell
314 void Calculate(double dt);
317 /** Get the center of gravity location of the ballonet
318 @return CoG location in the structural frame. */
319 const FGColumnVector3& GetXYZ(void) {return vXYZ;}
320 /** Get the center of gravity location of the ballonet
321 @return CoG location in the structural frame. */
322 double GetXYZ(int idx) {return vXYZ(idx);}
324 /** Get the current mass of the ballonets
325 @return mass in slug. */
326 double GetMass(void) {return Contents * M_air;}
328 /** Get the moments of inertia of the ballonet
329 @return moments of inertia matrix in slug ft<sup>2</sup>. */
330 FGMatrix33& GetInertia(void) {return ballonetJ;}
332 /** Get the current volume of the ballonet
333 @return volume in ft<sup>3</sup>. */
334 double GetVolume(void) {return Volume;}
335 /** Get the current heat flow into the ballonet
336 @return heat flow in lbs ft / sec. */
337 double GetHeatFlow(void) {return dU;} // [lbs ft / sec]
341 // Structural constants
342 double MaxVolume; // [ft�]
343 double MaxOverpressure; // [lbs/ft�]
344 FGColumnVector3 vXYZ; // [in]
345 double Xradius, Yradius, Zradius; // [ft]
346 double Xwidth, Ywidth, Zwidth; // [ft]
347 double ValveCoefficient; // [ft^4 sec / slug]
348 typedef vector <FGFunction*> CoeffArray;
349 CoeffArray HeatTransferCoeff; // [lbs ft / sec]
350 FGFunction* BlowerInput; // [ft^3 / sec]
353 double Pressure; // [lbs/ft�]
354 double Contents; // [mol]
355 double Volume; // [ft�]
356 double dVolumeIdeal; // [ft�]
357 double dU; // [lbs ft / sec]
358 double Temperature; // [Rankine]
359 double ValveOpen; // 0 <= ValveOpen <= 1 (or higher).
360 FGMatrix33 ballonetJ; // [slug foot�]
362 FGAuxiliary* Auxiliary;
363 FGAtmosphere* Atmosphere;
364 FGPropertyManager* PropertyManager;
365 FGInertial* Inertial;
366 void Debug(int from);
369 const static double R; // [lbs ft/(mol Rankine)]
370 const static double M_air; // [slug/mol]
371 const static double Cv_air; // [??]
374 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%