2001-10-05 20:27:01 +00:00
// IO360.hxx - a piston engine model currently for the IO360 engine fitted to the C172
// but with the potential to model other naturally aspirated piston engines
// given appropriate config input.
//
// Written by David Luff, started 2000.
// Based on code by Phil Schubert, started 1999.
2000-09-26 23:37:26 +00:00
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
2006-02-21 17:45:03 +00:00
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2001-10-05 20:27:01 +00:00
2000-09-26 23:37:26 +00:00
# ifndef _IO360_HXX_
# define _IO360_HXX_
2000-10-02 21:49:04 +00:00
# include <simgear/compiler.h>
2000-09-26 23:37:26 +00:00
# include <math.h>
2000-10-16 20:01:23 +00:00
class FGNewEngine {
2000-09-26 23:37:26 +00:00
private :
2001-10-05 20:27:01 +00:00
// These constants should probably be moved eventually
2000-09-26 23:37:26 +00:00
float CONVERT_CUBIC_INCHES_TO_METERS_CUBED ;
2001-10-05 20:27:01 +00:00
float CONVERT_HP_TO_WATTS ;
// Properties of working fluids
float Cp_air ; // J/KgK
float Cp_fuel ; // J/KgK
float calorific_value_fuel ; // W/Kg
float rho_fuel ; // kg/m^3
float rho_air ; // kg/m^3
2000-09-26 23:37:26 +00:00
2001-10-05 20:27:01 +00:00
// environment inputs
float p_amb_sea_level ; // Sea level ambient pressure in Pascals
float p_amb ; // Ambient pressure at current altitude in Pascals
float T_amb ; // ditto deg Kelvin
// Control inputs
float Throttle_Lever_Pos ; // 0 = Closed, 100 = Fully Open
float Propeller_Lever_Pos ; // 0 = Full Course 100 = Full Fine
float Mixture_Lever_Pos ; // 0 = Idle Cut Off 100 = Full Rich
2001-10-10 17:50:20 +00:00
int mag_pos ; // 0=off, 1=left, 2=right, 3=both.
bool starter ;
2001-10-05 20:27:01 +00:00
//misc
2000-09-26 23:37:26 +00:00
float IAS ;
2001-10-05 20:27:01 +00:00
double time_step ;
// Engine Specific Variables that should be read in from a config file
float MaxHP ; // Horsepower
float displacement ; // Cubic inches
float displacement_SI ; //m^3 (derived from above rather than read in)
float engine_inertia ; //kg.m^2
float prop_inertia ; //kg.m^2
float Max_Fuel_Flow ; // Units??? Do we need this variable any more??
// Engine specific variables that maybe should be read in from config but are pretty generic and won't vary much for a naturally aspirated piston engine.
float Max_Manifold_Pressure ; // inches Hg - typical manifold pressure at full throttle and typical max rpm
float Min_Manifold_Pressure ; // inches Hg - typical manifold pressure at idle (closed throttle)
float Max_RPM ; // rpm - this is really a bit of a hack and could be make redundant if the prop model works properly and takes tips at speed of sound into account.
float Min_RPM ; // rpm - possibly redundant ???
float Mag_Derate_Percent ; // Percentage reduction in power when mags are switched from 'both' to either 'L' or 'R'
float Gear_Ratio ; // Gearing between engine and propellor
float n_R ; // Number of cycles per power stroke - 2 for a 4 stroke engine.
// Engine Variables not read in from config file
float RPM ; // rpm
2000-09-26 23:37:26 +00:00
float Percentage_Power ; // Power output as percentage of maximum power output
2001-10-05 20:27:01 +00:00
float Manifold_Pressure ; // Inches Hg
float Fuel_Flow_gals_hr ; // USgals/hour
float Torque_lbft ; // lb-ft
float Torque_SI ; // Nm
2002-02-08 17:27:38 +00:00
float CHT ; // Cylinder head temperature deg K
This is a somewhat rough first attempt at modelling cylinder head
temperature. The cylinder head is assumed to be at uniform
temperature. Obviously this is incorrect, but it simplifies things a
lot, and we're just looking for the behaviour of CHT to be correct.
Energy transfer to the cylinder head is assumed to be one third of the
energy released by combustion at all conditions. This is a reasonable
estimate, although obviously in real life it varies with different
conditions and possibly with CHT itself. I've split energy transfer
from the cylinder head into 2 terms - free convection - ie convection
to stationary air, and forced convection, ie convection into flowing
air. The basic free convection equation is: dqdt = -hAdT Since we
don't know A and are going to set h quite arbitarily anyway I've
knocked A out and just wrapped it up in h - the only real significance
is that the units of h will be different but that dosn't really matter
to us anyway. In addition, we have the problem that the prop model
I'm currently using dosn't model the backwash from the prop which will
add to the velocity of the cooling air when the prop is turning, so
I've added an extra term to try and cope with this.
In real life, forced convection equations are genarally empirically
derived, and are quite complicated and generally contain such things
as the Reynolds and Nusselt numbers to various powers. The best
course of action would probably to find an empirical correlation from
the literature for a similar situation and try and get it to fit well.
However, for now I am using my own made up very simple correlation
for the energy transfer from the cylinder head:
dqdt = -(h1.dT) -(h2.m_dot.dT) -(h3.rpm.dT)
where dT is the temperature different between the cylinder head and
the surrounding air, m_dot is the mass flow rate of cooling air
through an arbitary volume, rpm is the engine speed in rpm (this is
the backwash term), and h1, h2, h3 are co-efficients which we can play
with to attempt to get the CHT behaviour to match real life.
In order to change the values of CHT that the engine settles down at
at various conditions, have a play with h1, h2 and h3. In order to
change the rate of heating/cooling without affecting equilibrium
values alter the cylinder head mass, which is really quite arbitary.
Bear in mind that altering h1, h2 and h3 will also alter the rate of
heating or cooling as well as equilibrium values, but altering the
cylinder head mass will only alter the rate. It would I suppose be
better to read the values from file to avoid the necessity for
re-compilation every time I change them.
2000-10-27 21:33:07 +00:00
float CHT_degF ; // Ditto in deg Fahrenheit
2000-09-26 23:37:26 +00:00
float Mixture ;
float Oil_Pressure ; // PSI
float Oil_Temp ; // Deg C
2001-10-05 20:27:01 +00:00
float current_oil_temp ; // deg K
/**** one of these is superfluous !!!!***/
2000-09-26 23:37:26 +00:00
float HP ; // Current power output in HP
float Power_SI ; // Current power output in Watts
float RPS ;
2001-10-05 20:27:01 +00:00
float angular_velocity_SI ; // rad/s
float Torque_FMEP ; // The component of Engine torque due to FMEP (Nm)
float Torque_Imbalance ; // difference between engine and prop torque
float EGT ; // Exhaust gas temperature deg K
float EGT_degF ; // Exhaust gas temperature deg Fahrenheit
2000-09-26 23:37:26 +00:00
float volumetric_efficiency ;
float combustion_efficiency ;
2001-10-05 20:27:01 +00:00
float equivalence_ratio ; // ratio of stoichiometric AFR over actual AFR
float thi_sea_level ; // the equivalence ratio we would be running at assuming sea level air denisity in the manifold
float v_dot_air ; // volume flow rate of air into engine - m^3/s
float m_dot_air ; // mass flow rate of air into engine - kg/s
float m_dot_fuel ; // mass flow rate of fuel into engine - kg/s
float swept_volume ; // total engine swept volume - m^3
/********* swept volume or the geometry used to calculate it should be in the config read section surely ??? ******/
float True_Manifold_Pressure ; //in Hg - actual manifold gauge pressure
float rho_air_manifold ; // denisty of air in the manifold - kg/m^3
float R_air ; // Gas constant of air (287) UNITS???
float delta_T_exhaust ; // Temperature change of exhaust this time step - degK
float heat_capacity_exhaust ; // exhaust gas specific heat capacity - J/kgK
float enthalpy_exhaust ; // Enthalpy at current exhaust gas conditions - UNITS???
float Percentage_of_best_power_mixture_power ; // Current power as a percentage of what power we would have at the same conditions but at best power mixture
2000-09-26 23:37:26 +00:00
float abstract_mixture ; //temporary hack
2000-09-28 22:49:33 +00:00
float angular_acceleration ; //rad/s^2
2001-09-19 22:58:29 +00:00
float FMEP ; //Friction Mean Effective Pressure (Pa)
2001-10-05 20:27:01 +00:00
// Various bits of housekeeping describing the engines state.
bool running ; // flag to indicate the engine is running self sustaining
bool cranking ; // flag to indicate the engine is being cranked
int crank_counter ; // Number of iterations that the engine has been cranked non-stop
bool spark ; // flag to indicate a spark is available
bool fuel ; // flag to indicate fuel is available
2000-09-26 23:37:26 +00:00
2001-03-22 16:27:16 +00:00
// Propellor Variables
2001-10-05 20:27:01 +00:00
float FGProp1_RPS ; // rps
2001-02-02 20:55:41 +00:00
float prop_torque ; // Nm
float prop_thrust ; // Newtons
2001-10-05 20:27:01 +00:00
double prop_diameter ; // meters
double blade_angle ; // degrees
2000-09-26 23:37:26 +00:00
2001-10-05 20:27:01 +00:00
// MEMBER FUNCTIONS
2000-09-26 23:37:26 +00:00
// Calculate Engine RPM based on Propellor Lever Position
2001-03-22 16:27:16 +00:00
float Calc_Engine_RPM ( float Position ) ;
// Calculate Manifold Pressure based on throttle lever position
// Note that this is simplistic and needs altering to include engine speed effects
float Calc_Manifold_Pressure ( float LeverPosn , float MaxMan , float MinMan ) ;
2000-09-26 23:37:26 +00:00
// Calculate combustion efficiency based on equivalence ratio
float Lookup_Combustion_Efficiency ( float thi_actual ) ;
2001-03-22 16:27:16 +00:00
// Calculate percentage of best power mixture power based on equivalence ratio
float Power_Mixture_Correlation ( float thi_actual ) ;
2001-10-05 20:27:01 +00:00
// Calculate exhaust gas temperature change
2000-09-26 23:37:26 +00:00
float Calculate_Delta_T_Exhaust ( void ) ;
2001-10-05 20:27:01 +00:00
// Calculate cylinder head temperature
2002-02-15 22:00:49 +00:00
void Calc_CHT ( void ) ;
2001-10-05 20:27:01 +00:00
2002-02-08 17:27:38 +00:00
// Calculate exhaust gas temperature
2002-02-15 22:00:49 +00:00
void Calc_EGT ( void ) ;
2001-10-05 20:27:01 +00:00
// Calculate fuel flow in gals/hr
2002-02-15 22:00:49 +00:00
void Calc_Fuel_Flow_Gals_Hr ( void ) ;
2001-10-05 20:27:01 +00:00
// Calculate current percentage power
2002-02-15 22:00:49 +00:00
void Calc_Percentage_Power ( bool mag_left , bool mag_right ) ;
2001-10-05 20:27:01 +00:00
2001-03-22 16:27:16 +00:00
// Calculate Oil Temperature
2001-10-05 20:27:01 +00:00
float Calc_Oil_Temp ( float oil_temp ) ;
2001-03-22 16:27:16 +00:00
// Calculate Oil Pressure
float Calc_Oil_Press ( float Oil_Temp , float Engine_RPM ) ;
2001-10-05 20:27:01 +00:00
// Propeller calculations.
2002-02-15 22:00:49 +00:00
void Do_Prop_Calcs ( void ) ;
2001-10-05 20:27:01 +00:00
2000-09-26 23:37:26 +00:00
public :
2001-10-05 20:27:01 +00:00
// ofstream outfile;
2000-09-26 23:37:26 +00:00
//constructor
2000-10-16 20:01:23 +00:00
FGNewEngine ( ) {
This is a somewhat rough first attempt at modelling cylinder head
temperature. The cylinder head is assumed to be at uniform
temperature. Obviously this is incorrect, but it simplifies things a
lot, and we're just looking for the behaviour of CHT to be correct.
Energy transfer to the cylinder head is assumed to be one third of the
energy released by combustion at all conditions. This is a reasonable
estimate, although obviously in real life it varies with different
conditions and possibly with CHT itself. I've split energy transfer
from the cylinder head into 2 terms - free convection - ie convection
to stationary air, and forced convection, ie convection into flowing
air. The basic free convection equation is: dqdt = -hAdT Since we
don't know A and are going to set h quite arbitarily anyway I've
knocked A out and just wrapped it up in h - the only real significance
is that the units of h will be different but that dosn't really matter
to us anyway. In addition, we have the problem that the prop model
I'm currently using dosn't model the backwash from the prop which will
add to the velocity of the cooling air when the prop is turning, so
I've added an extra term to try and cope with this.
In real life, forced convection equations are genarally empirically
derived, and are quite complicated and generally contain such things
as the Reynolds and Nusselt numbers to various powers. The best
course of action would probably to find an empirical correlation from
the literature for a similar situation and try and get it to fit well.
However, for now I am using my own made up very simple correlation
for the energy transfer from the cylinder head:
dqdt = -(h1.dT) -(h2.m_dot.dT) -(h3.rpm.dT)
where dT is the temperature different between the cylinder head and
the surrounding air, m_dot is the mass flow rate of cooling air
through an arbitary volume, rpm is the engine speed in rpm (this is
the backwash term), and h1, h2, h3 are co-efficients which we can play
with to attempt to get the CHT behaviour to match real life.
In order to change the values of CHT that the engine settles down at
at various conditions, have a play with h1, h2 and h3. In order to
change the rate of heating/cooling without affecting equilibrium
values alter the cylinder head mass, which is really quite arbitary.
Bear in mind that altering h1, h2 and h3 will also alter the rate of
heating or cooling as well as equilibrium values, but altering the
cylinder head mass will only alter the rate. It would I suppose be
better to read the values from file to avoid the necessity for
re-compilation every time I change them.
2000-10-27 21:33:07 +00:00
// outfile.open("FGNewEngine.dat", ios::out|ios::trunc);
2000-09-26 23:37:26 +00:00
}
//destructor
2000-10-16 20:01:23 +00:00
~ FGNewEngine ( ) {
2000-09-28 22:49:33 +00:00
// outfile.close();
2000-09-26 23:37:26 +00:00
}
// set initial default values
2000-09-28 22:49:33 +00:00
void init ( double dt ) ;
2000-09-26 23:37:26 +00:00
// update the engine model based on current control positions
void update ( ) ;
inline void set_IAS ( float value ) { IAS = value ; }
inline void set_Throttle_Lever_Pos ( float value ) {
Throttle_Lever_Pos = value ;
}
inline void set_Propeller_Lever_Pos ( float value ) {
Propeller_Lever_Pos = value ;
}
inline void set_Mixture_Lever_Pos ( float value ) {
Mixture_Lever_Pos = value ;
}
2001-10-10 17:50:20 +00:00
// set the magneto switch position
inline void set_Magneto_Switch_Pos ( int value ) {
mag_pos = value ;
}
inline void setStarterFlag ( bool flag ) {
starter = flag ;
}
2001-03-22 16:27:16 +00:00
// set ambient pressure - takes pounds per square foot
inline void set_p_amb ( float value ) {
p_amb = value * 47.88026 ;
// Convert to Pascals
}
// set ambient temperature - takes degrees Rankine
inline void set_T_amb ( float value ) {
T_amb = value * 0.555555555556 ;
// Convert to degrees Kelvin
}
2000-09-26 23:37:26 +00:00
// accessors
inline float get_RPM ( ) const { return RPM ; }
2001-03-22 16:27:16 +00:00
inline float get_Manifold_Pressure ( ) const { return True_Manifold_Pressure ; }
// inline float get_Rho() const { return Rho; }
2000-09-26 23:37:26 +00:00
inline float get_MaxHP ( ) const { return MaxHP ; }
inline float get_Percentage_Power ( ) const { return Percentage_Power ; }
2000-11-02 17:01:09 +00:00
inline float get_EGT ( ) const { return EGT_degF ; } // Returns EGT in Fahrenheit
inline float get_CHT ( ) const { return CHT_degF ; } // Note this returns CHT in Fahrenheit
2000-09-26 23:37:26 +00:00
inline float get_prop_thrust_SI ( ) const { return prop_thrust ; }
2001-02-02 20:55:41 +00:00
inline float get_prop_thrust_lbs ( ) const { return ( prop_thrust * 0.2248 ) ; }
2001-03-01 16:32:29 +00:00
inline float get_fuel_flow_gals_hr ( ) const { return ( Fuel_Flow_gals_hr ) ; }
2001-10-05 20:27:01 +00:00
inline float get_oil_temp ( ) const { return ( ( current_oil_temp * 1.8 ) - 459.67 ) ; }
2001-10-10 17:50:20 +00:00
inline bool getRunningFlag ( ) const { return running ; }
inline bool getCrankingFlag ( ) const { return cranking ; }
inline bool getStarterFlag ( ) const { return starter ; }
2000-09-26 23:37:26 +00:00
} ;
2001-02-02 20:55:41 +00:00
# endif // _IO360_HXX_