-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module: FGEngine.cpp
- Author: Jon Berndt
- Date started: 01/21/99
- Called by: FGAircraft
-
- ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
-
- 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 Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-See header file.
-
-HISTORY
---------------------------------------------------------------------------------
-01/21/99 JSB Created
-09/03/99 JSB Changed Rocket thrust equation to correct -= Thrust instead of
- += Thrust (thanks to Tony Peden)
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifdef FGFS
-# include <simgear/compiler.h>
-# ifdef SG_HAVE_STD_INCLUDES
-# include <fstream>
-# else
-# include <fstream.h>
-# endif
-#else
-# if defined(sgi) && !defined(__GNUC__)
-# include <fstream.h>
-# else
-# include <fstream>
-# endif
-#endif
-
-#include "FGEngine.h"
-#include "FGTank.h"
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_ENGINE;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-
-FGEngine::FGEngine(FGFDMExec* exec) {
- FDMExec = exec;
- State = FDMExec->GetState();
- Atmosphere = FDMExec->GetAtmosphere();
- FCS = FDMExec->GetFCS();
- Propulsion = FDMExec->GetPropulsion();
- Aircraft = FDMExec->GetAircraft();
- Translation = FDMExec->GetTranslation();
- Rotation = FDMExec->GetRotation();
- Position = FDMExec->GetPosition();
- Auxiliary = FDMExec->GetAuxiliary();
- Output = FDMExec->GetOutput();
-
- Mixture = 1.0; // FIXME: get actual value\r
- Thrust = PctPower = 0.0;
- Starved = Flameout = false;
- Running = true;
-
- if (debug_lvl & 2) cout << "Instantiated: FGEngine" << endl;
- TrimMode = false;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGEngine::~FGEngine()
-{
- if (debug_lvl & 2) cout << "Destroyed: FGEngine" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-// This base class function should be called from within the
-// derived class' Calculate() function before any other calculations are done.
-// This base class method removes fuel from the fuel tanks as appropriate,
-// and sets the starved flag if necessary.
-
-void FGEngine::ConsumeFuel(void) {
- float Fshortage, Oshortage;
- FGTank* Tank;
-
- if (TrimMode) return;
-
- Fshortage = Oshortage = 0.0;
- for (unsigned int i=0; i<SourceTanks.size(); i++) {
- Tank = Propulsion->GetTank(i);
- if (Tank->GetType() == FGTank::ttFUEL) {
- Fshortage += Tank->Reduce(CalcFuelNeed()/Propulsion->GetnumSelectedFuelTanks());
- } else {
- Oshortage += Tank->Reduce(CalcOxidizerNeed()/Propulsion->GetnumSelectedOxiTanks());
- }
- }
-
- if (Fshortage < 0.00 || Oshortage < 0.00) Starved = true;
- else Starved = false;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-float FGEngine::CalcFuelNeed(void) {
- FuelNeed = SLFuelFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
- return FuelNeed;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-float FGEngine::CalcOxidizerNeed(void) {
- OxidizerNeed = SLOxiFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();
- return OxidizerNeed;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGEngine::SetPlacement(float x, float y, float z, float pitch, float yaw) {
- X = x;
- Y = y;
- Z = z;
- EnginePitch = pitch;
- EngineYaw = yaw;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGEngine::AddFeedTank(int tkID)
-{
- SourceTanks.push_back(tkID);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGEngine::Debug(void)
-{
- //TODO: Add your source code here
-}
-
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+ \r
+ Module: FGEngine.cpp\r
+ Author: Jon Berndt\r
+ Date started: 01/21/99\r
+ Called by: FGAircraft\r
+ \r
+ ------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------\r
+ \r
+ This program is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License as published by the Free Software\r
+ Foundation; either version 2 of the License, or (at your option) any later\r
+ version.\r
+ \r
+ This program is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details.\r
+ \r
+ You should have received a copy of the GNU General Public License along with\r
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
+ Place - Suite 330, Boston, MA 02111-1307, USA.\r
+ \r
+ Further information about the GNU General Public License can also be found on\r
+ the world wide web at http://www.gnu.org.\r
+ \r
+FUNCTIONAL DESCRIPTION\r
+--------------------------------------------------------------------------------\r
+See header file.\r
+ \r
+HISTORY\r
+--------------------------------------------------------------------------------\r
+01/21/99 JSB Created\r
+09/03/99 JSB Changed Rocket thrust equation to correct -= Thrust instead of\r
+ += Thrust (thanks to Tony Peden)\r
+ \r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+INCLUDES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#ifdef FGFS\r
+# include <simgear/compiler.h>\r
+# ifdef SG_HAVE_STD_INCLUDES\r
+# include <fstream>\r
+# else\r
+# include <fstream.h>\r
+# endif\r
+#else\r
+# if defined(sgi) && !defined(__GNUC__)\r
+# include <fstream.h>\r
+# else\r
+# include <fstream>\r
+# endif\r
+#endif\r
+\r
+#include "FGEngine.h"\r
+#include "FGTank.h"\r
+\r
+static const char *IdSrc = "$Id$";\r
+static const char *IdHdr = ID_ENGINE;\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+CLASS IMPLEMENTATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+\r
+FGEngine::FGEngine(FGFDMExec* exec) {\r
+ FDMExec = exec;\r
+ State = FDMExec->GetState();\r
+ Atmosphere = FDMExec->GetAtmosphere();\r
+ FCS = FDMExec->GetFCS();\r
+ Propulsion = FDMExec->GetPropulsion();\r
+ Aircraft = FDMExec->GetAircraft();\r
+ Translation = FDMExec->GetTranslation();\r
+ Rotation = FDMExec->GetRotation();\r
+ Position = FDMExec->GetPosition();\r
+ Auxiliary = FDMExec->GetAuxiliary();\r
+ Output = FDMExec->GetOutput();\r
+\r
+ Mixture = 1.0; // FIXME: get actual value
+\r
+ Thrust = PctPower = 0.0;\r
+ Starved = Flameout = false;\r
+ Running = false;\r
+ Cranking = false;\r
+\r
+ if (debug_lvl & 2) cout << "Instantiated: FGEngine" << endl;\r
+ TrimMode = false;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+FGEngine::~FGEngine()\r
+{\r
+ if (debug_lvl & 2) cout << "Destroyed: FGEngine" << endl;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+// This base class function should be called from within the\r
+// derived class' Calculate() function before any other calculations are done.\r
+// This base class method removes fuel from the fuel tanks as appropriate,\r
+// and sets the starved flag if necessary.\r
+\r
+void FGEngine::ConsumeFuel(void) {\r
+ float Fshortage, Oshortage;\r
+ FGTank* Tank;\r
+\r
+ if (TrimMode) return;\r
+\r
+ Fshortage = Oshortage = 0.0;\r
+ for (unsigned int i=0; i<SourceTanks.size(); i++) {\r
+ Tank = Propulsion->GetTank(i);\r
+ if (Tank->GetType() == FGTank::ttFUEL) {\r
+ Fshortage += Tank->Reduce(CalcFuelNeed()/Propulsion->GetnumSelectedFuelTanks());\r
+ } else {\r
+ Oshortage += Tank->Reduce(CalcOxidizerNeed()/Propulsion->GetnumSelectedOxiTanks());\r
+ }\r
+ }\r
+\r
+ if (Fshortage < 0.00 || Oshortage < 0.00) Starved = true;\r
+ else Starved = false;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGEngine::CalcFuelNeed(void) {\r
+ FuelNeed = SLFuelFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();\r
+ return FuelNeed;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGEngine::CalcOxidizerNeed(void) {\r
+ OxidizerNeed = SLOxiFlowMax*PctPower*State->Getdt()*Propulsion->GetRate();\r
+ return OxidizerNeed;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGEngine::SetPlacement(float x, float y, float z, float pitch, float yaw) {\r
+ X = x;\r
+ Y = y;\r
+ Z = z;\r
+ EnginePitch = pitch;\r
+ EngineYaw = yaw;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGEngine::AddFeedTank(int tkID)\r
+{\r
+ SourceTanks.push_back(tkID);\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGEngine::Debug(void)\r
+{\r
+ //TODO: Add your source code here\r
+}\r
+\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Module: FGPiston.cpp
- Author: Jon S. Berndt
- Date started: 09/12/2000
- Purpose: This module models a Piston engine
-
- ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) --------------
-
- 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 Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-FUNCTIONAL DESCRIPTION
---------------------------------------------------------------------------------
-
-This class descends from the FGEngine class and models a Piston engine based on
-parameters given in the engine config file for this class
-
-HISTORY
---------------------------------------------------------------------------------
-09/12/2000 JSB Created
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGDefs.h"
-#include "FGPiston.h"
-#include "FGPropulsion.h"
-
-static const char *IdSrc = "$Id$";
-static const char *IdHdr = ID_PISTON;
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS IMPLEMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg)
- : FGEngine(exec),
- MinManifoldPressure_inHg(6.5),
- MaxManifoldPressure_inHg(28.5),
- Displacement(360),
- MaxHP(200),
- Cycles(2),
- IdleRPM(900),
- // Set constants
- CONVERT_CUBIC_INCHES_TO_METERS_CUBED(1.638706e-5),
- R_air(287.3),
- rho_fuel(800), // estimate
- calorific_value_fuel(47.3e6),
- Cp_air(1005),
- Cp_fuel(1700),
- running(true), // FIXME: FGEngine already has 'Running'
- cranking(false)
-{
- string token;
-
- Name = Eng_cfg->GetValue("NAME");
- Eng_cfg->GetNextConfigLine();
- while (Eng_cfg->GetValue() != "/FG_PISTON") {
- *Eng_cfg >> token;
- if (token == "MINMP") *Eng_cfg >> MinManifoldPressure_inHg;
- else if (token == "MAXMP") *Eng_cfg >> MaxManifoldPressure_inHg;
- else if (token == "DISPLACEMENT") *Eng_cfg >> Displacement;
- else if (token == "MAXHP") *Eng_cfg >> MaxHP;
- else if (token == "CYCLES") *Eng_cfg >> Cycles;
- else if (token == "IDLERPM") *Eng_cfg >> IdleRPM;
- else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle;
- else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;
- else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax;
- else cerr << "Unhandled token in Engine config file: " << token << endl;
- }
-
- if (debug_lvl > 0) {
- cout << "\n Engine Name: " << Name << endl;
- cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl;
- cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl;
- cout << " Displacement: " << Displacement << endl;
- cout << " MaxHP: " << MaxHP << endl;
- cout << " Cycles: " << Cycles << endl;
- cout << " IdleRPM: " << IdleRPM << endl;
- cout << " MaxThrottle: " << MaxThrottle << endl;
- cout << " MinThrottle: " << MinThrottle << endl;
- cout << " SLFuelFlowMax: " << SLFuelFlowMax << endl;
- }
-
- Type = etPiston;
- EngineNumber = 0; // FIXME: this should be the actual number
- OilTemp_degK = 298; // FIXME: should be initialized in FGEngine
-
- dt = State->Getdt();
-
- // Initialisation
- volumetric_efficiency = 0.8; // Actually f(speed, load) but this will get us running
-
- if (debug_lvl & 2) cout << "Instantiated: FGPiston" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-FGPiston::~FGPiston()
-{
- if (debug_lvl & 2) cout << "Destroyed: FGPiston" << endl;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-float FGPiston::Calculate(float PowerRequired)
-{
- float h,EngineMaxPower;
-
- // FIXME: calculate from actual fuel flow
- ConsumeFuel();
-
- Throttle = FCS->GetThrottlePos(EngineNumber);
- Mixture = FCS->GetMixturePos(EngineNumber);
-
- //
- // Input values.
- //
- // convert from lbs/ft2 to Pa
- p_amb = Atmosphere->GetPressure() * 48;
- p_amb_sea_level = Atmosphere->GetPressureSL() * 48;
- // convert from Rankine to Kelvin
- T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0);
- RPM = Propulsion->GetThruster(EngineNumber)->GetRPM();
- if (RPM < IdleRPM) // kludge
- RPM = IdleRPM;
- IAS = Auxiliary->GetVcalibratedKTS();
-
- if (Mixture >= 0.5) {
- doEngineStartup();
- doManifoldPressure();
- doAirFlow();
- doFuelFlow();
- doEnginePower();
- doEGT();
- doCHT();
- doOilTemperature();
- doOilPressure();
- } else {
- HP = 0;
- }
-
- PowerAvailable = (HP * HPTOFTLBSSEC) - PowerRequired;
- return PowerAvailable;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Look up the power/mixture correlation.
- *
- * FIXME: this should use JSBSim's interpolation support.
- */
-
-static float Power_Mixture_Correlation(float thi_actual)
-{
- float AFR_actual = 14.7 / thi_actual;
- const int NUM_ELEMENTS = 13;
- float AFR[NUM_ELEMENTS] =
- {(14.7/1.6), 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, (14.7/0.6)};
- float mixPerPow[NUM_ELEMENTS] =
- {78, 86, 93.5, 98, 100, 99, 96.4, 92.5, 88, 83, 78.5, 74, 58};
- float mixPerPow_actual = 0.0f;
- float factor;
- float dydx;
-
- int i;
- int j = NUM_ELEMENTS;
-
- for (i=0;i<j;i++) {
- if (i == (j-1)) {
- dydx = (mixPerPow[i] - mixPerPow[i-1]) / (AFR[i] - AFR[i-1]);
- mixPerPow_actual = mixPerPow[i] + dydx * (AFR_actual - AFR[i]);
- return mixPerPow_actual;
- }
- if ((i == 0) && (AFR_actual < AFR[i])) {
- dydx = (mixPerPow[i] - mixPerPow[i-1]) / (AFR[i] - AFR[i-1]);
- mixPerPow_actual = mixPerPow[i] + dydx * (AFR_actual - AFR[i]);
- return mixPerPow_actual;
- }
- if (AFR_actual == AFR[i]) {
- mixPerPow_actual = mixPerPow[i];
- return mixPerPow_actual;
- }
- if ((AFR_actual > AFR[i]) && (AFR_actual < AFR[i + 1])) {
- factor = (AFR_actual - AFR[i]) / (AFR[i+1] - AFR[i]);
- mixPerPow_actual = (factor * (mixPerPow[i+1] - mixPerPow[i])) + mixPerPow[i];
- return mixPerPow_actual;
- }
- }
-
- cerr << "ERROR: error in FGNewEngine::Power_Mixture_Correlation\n";
- return mixPerPow_actual;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Look up the combustion efficiency.
- *
- *
- * FIXME: this should use JSBSim's interpolation support.
- */
-
-static float Lookup_Combustion_Efficiency(float thi_actual)
-{
- const int NUM_ELEMENTS = 11;
- float thi[NUM_ELEMENTS] = {0.0, 0.9, 1.0, 1.05, 1.1, 1.15, 1.2, 1.3, 1.4, 1.5, 1.6}; //array of equivalence ratio values
- float neta_comb[NUM_ELEMENTS] = {0.98, 0.98, 0.97, 0.95, 0.9, 0.85, 0.79, 0.7, 0.63, 0.57, 0.525}; //corresponding array of combustion efficiency values
- //combustion efficiency values from Heywood, "Internal Combustion Engine Fundamentals", ISBN 0-07-100499-8
- float neta_comb_actual = 0.0f;
- float factor;
-
- int i;
- int j = NUM_ELEMENTS; //This must be equal to the number of elements in the lookup table arrays
-
- for (i=0;i<j;i++) {
- if(i == (j-1)) {
- // Assume linear extrapolation of the slope between the last two points beyond the last point
- float dydx = (neta_comb[i] - neta_comb[i-1]) / (thi[i] - thi[i-1]);
- neta_comb_actual = neta_comb[i] + dydx * (thi_actual - thi[i]);
- return neta_comb_actual;
- }
- if(thi_actual == thi[i]) {
- neta_comb_actual = neta_comb[i];
- return neta_comb_actual;
- }
- if((thi_actual > thi[i]) && (thi_actual < thi[i + 1])) {
- //do linear interpolation between the two points
- factor = (thi_actual - thi[i]) / (thi[i+1] - thi[i]);
- neta_comb_actual = (factor * (neta_comb[i+1] - neta_comb[i])) + neta_comb[i];
- return neta_comb_actual;
- }
- }
-
- //if we get here something has gone badly wrong
- cerr << "ERROR: error in FGNewEngine::Lookup_Combustion_Efficiency\n";
- return neta_comb_actual;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Start or stop the engine.
- */
-
-void FGPiston::doEngineStartup(void)
-{
- // TODO: check magnetos, spark, starter, etc. and decide whether
- // engine is running
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-/**
- * Calculate the nominal manifold pressure in inches hg
- *
- * This function calculates nominal manifold pressure directly
- * from the throttle position, and does not adjust it for the
- * difference between the pressure at sea level and the pressure
- * at the current altitude (that adjustment takes place in
- * {@link #doEnginePower}).
- *
- * TODO: changes in MP should not be instantaneous -- introduce
- * a lag between throttle changes and MP changes, to allow pressure
- * to build up or disperse.
- *
- * Inputs: MinManifoldPressure_inHg, MaxManifoldPressure_inHg, Throttle
- *
- * Outputs: ManifoldPressure_inHg
- */
-
-void FGPiston::doManifoldPressure(void)
-{
- ManifoldPressure_inHg = MinManifoldPressure_inHg +
- (Throttle * (MaxManifoldPressure_inHg - MinManifoldPressure_inHg));
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the air flow through the engine.
- *
- * Inputs: p_amb, R_air, T_amb, ManifoldPressure_inHg, Displacement,
- * RPM, volumetric_efficiency
- *
- * Outputs: rho_air, m_dot_air
- */
-
-void FGPiston::doAirFlow(void)
-{
- rho_air = p_amb / (R_air * T_amb);
- float rho_air_manifold = rho_air * ManifoldPressure_inHg / 29.6;
- float displacement_SI = Displacement * CONVERT_CUBIC_INCHES_TO_METERS_CUBED;
- float swept_volume = (displacement_SI * (RPM/60)) / 2;
- float v_dot_air = swept_volume * volumetric_efficiency;
- m_dot_air = v_dot_air * rho_air_manifold;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the fuel flow into the engine.
- *
- * Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air
- *
- * Outputs: equivalence_ratio, m_dot_fuel
- */
-
-void FGPiston::doFuelFlow(void)
-{
- float thi_sea_level = 1.3 * Mixture;
- equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb;
- m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the power produced by the engine.
- *
- * <p>Currently, the JSBSim propellor model does not allow the
- * engine to produce enough RPMs to get up to a high horsepower.
- * When tested with sufficient RPM, it has no trouble reaching
- * 200HP.</p>
- *
- * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb,
- * equivalence_ratio, Cycles, MaxHP
- *
- * Outputs: Percentage_Power, HP
- */
-
-void FGPiston::doEnginePower(void)
-{
- float True_ManifoldPressure_inHg = ManifoldPressure_inHg * p_amb / p_amb_sea_level;
- float ManXRPM = True_ManifoldPressure_inHg * RPM;
- // FIXME: this needs to be generalized
- Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0;
- float T_amb_degF = (T_amb * 1.8) - 459.67;
- float T_amb_sea_lev_degF = (288 * 1.8) - 459.67;
- Percentage_Power =
- Percentage_Power + ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120);
- float Percentage_of_best_power_mixture_power =
- Power_Mixture_Correlation(equivalence_ratio);
- Percentage_Power =
- Percentage_Power * Percentage_of_best_power_mixture_power / 100.0;
- if (Percentage_Power < 0.0)
- Percentage_Power = 0.0;
- else if (Percentage_Power > 100.0)
- Percentage_Power = 100.0;
- HP = Percentage_Power * MaxHP / 100.0;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the exhaust gas temperature.
- *
- * Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel,
- * Cp_air, m_dot_air, Cp_fuel, m_dot_fuel, T_amb, Percentage_Power
- *
- * Outputs: combustion_efficiency, ExhaustGasTemp_degK
- */
-
-void FGPiston::doEGT(void)
-{
- combustion_efficiency = Lookup_Combustion_Efficiency(equivalence_ratio);
- float enthalpy_exhaust = m_dot_fuel * calorific_value_fuel *
- combustion_efficiency * 0.33;
- float heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);
- float delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust;
- ExhaustGasTemp_degK = T_amb + delta_T_exhaust;
- ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the cylinder head temperature.
- *
- * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,
- * combustion_efficiency, RPM
- *
- * Outputs: CylinderHeadTemp_degK
- */
-
-void FGPiston::doCHT(void)
-{
- float h1 = -95.0;
- float h2 = -3.95;
- float h3 = -0.05;
-
- float arbitary_area = 1.0;
- float CpCylinderHead = 800.0;
- float MassCylinderHead = 8.0;
-
- float temperature_difference = CylinderHeadTemp_degK - T_amb;
- float v_apparent = IAS * 0.5144444;
- float v_dot_cooling_air = arbitary_area * v_apparent;
- float m_dot_cooling_air = v_dot_cooling_air * rho_air;
- float dqdt_from_combustion =
- m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
- float dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) +
- (h3 * RPM * temperature_difference);
- float dqdt_free = h1 * temperature_difference;
- float dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free;
-
- float HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead;
-
- CylinderHeadTemp_degK = dqdt_cylinder_head / HeatCapacityCylinderHead;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the oil temperature.
- *
- * Inputs: Percentage_Power, running flag.
- *
- * Outputs: OilTemp_degK
- */
-
-void FGPiston::doOilTemperature(void)
-{
- float idle_percentage_power = 2.3; // approximately
- float target_oil_temp; // Steady state oil temp at the current engine conditions
- float time_constant; // The time constant for the differential equation
-
- if (running) {
- target_oil_temp = 363;
- time_constant = 500; // Time constant for engine-on idling.
- if (Percentage_Power > idle_percentage_power) {
- time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power
- }
- } else {
- target_oil_temp = 298;
- time_constant = 1000; // Time constant for engine-off; reflects the fact that oil is no longer getting circulated
- }
-
- float dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant;
-
- OilTemp_degK += (dOilTempdt * dt);
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/**
- * Calculate the oil pressure.
- *
- * Inputs: RPM
- *
- * Outputs: OilPressure_psi
- */
-
-void FGPiston::doOilPressure(void)
-{
- float Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine
- float Oil_Press_RPM_Max = 1800; // FIXME: may vary by engine
- float Design_Oil_Temp = 85; // FIXME: may vary by engine
- // FIXME: WRONG!!! (85 degK???)
- float Oil_Viscosity_Index = 0.25;
-
- OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM;
-
- if (OilPressure_psi >= Oil_Press_Relief_Valve) {
- OilPressure_psi = Oil_Press_Relief_Valve;
- }
-
- OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index;
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPiston::Debug(void)
-{
- //TODO: Add your source code here
-}
-
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+ Module: FGPiston.cpp\r
+ Author: Jon S. Berndt\r
+ Date started: 09/12/2000\r
+ Purpose: This module models a Piston engine\r
+\r
+ ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) --------------\r
+\r
+ This program is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License as published by the Free Software\r
+ Foundation; either version 2 of the License, or (at your option) any later\r
+ version.\r
+\r
+ This program is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details.\r
+\r
+ You should have received a copy of the GNU General Public License along with\r
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
+ Place - Suite 330, Boston, MA 02111-1307, USA.\r
+\r
+ Further information about the GNU General Public License can also be found on\r
+ the world wide web at http://www.gnu.org.\r
+\r
+FUNCTIONAL DESCRIPTION\r
+--------------------------------------------------------------------------------\r
+\r
+This class descends from the FGEngine class and models a Piston engine based on\r
+parameters given in the engine config file for this class\r
+\r
+HISTORY\r
+--------------------------------------------------------------------------------\r
+09/12/2000 JSB Created\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+INCLUDES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#include "FGDefs.h"\r
+#include "FGPiston.h"\r
+#include "FGPropulsion.h"\r
+\r
+static const char *IdSrc = "$Id$";\r
+static const char *IdHdr = ID_PISTON;\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+CLASS IMPLEMENTATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+FGPiston::FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg)\r
+ : FGEngine(exec),\r
+ MinManifoldPressure_inHg(6.5),\r
+ MaxManifoldPressure_inHg(28.5),\r
+ Displacement(360),\r
+ MaxHP(200),\r
+ Cycles(2),\r
+ IdleRPM(600),\r
+ // Set constants\r
+ CONVERT_CUBIC_INCHES_TO_METERS_CUBED(1.638706e-5),\r
+ R_air(287.3),\r
+ rho_fuel(800), // estimate\r
+ calorific_value_fuel(47.3e6),\r
+ Cp_air(1005),\r
+ Cp_fuel(1700)\r
+{\r
+ string token;\r
+\r
+ Name = Eng_cfg->GetValue("NAME");\r
+ Eng_cfg->GetNextConfigLine();\r
+ while (Eng_cfg->GetValue() != "/FG_PISTON") {\r
+ *Eng_cfg >> token;\r
+ if (token == "MINMP") *Eng_cfg >> MinManifoldPressure_inHg;\r
+ else if (token == "MAXMP") *Eng_cfg >> MaxManifoldPressure_inHg;\r
+ else if (token == "DISPLACEMENT") *Eng_cfg >> Displacement;\r
+ else if (token == "MAXHP") *Eng_cfg >> MaxHP;\r
+ else if (token == "CYCLES") *Eng_cfg >> Cycles;\r
+ else if (token == "IDLERPM") *Eng_cfg >> IdleRPM;\r
+ else if (token == "MAXTHROTTLE") *Eng_cfg >> MaxThrottle;\r
+ else if (token == "MINTHROTTLE") *Eng_cfg >> MinThrottle;\r
+ else if (token == "SLFUELFLOWMAX") *Eng_cfg >> SLFuelFlowMax;\r
+ else cerr << "Unhandled token in Engine config file: " << token << endl;\r
+ }\r
+\r
+ if (debug_lvl > 0) {\r
+ cout << "\n Engine Name: " << Name << endl;\r
+ cout << " MinManifoldPressure: " << MinManifoldPressure_inHg << endl;\r
+ cout << " MaxManifoldPressure: " << MaxManifoldPressure_inHg << endl;\r
+ cout << " Displacement: " << Displacement << endl;\r
+ cout << " MaxHP: " << MaxHP << endl;\r
+ cout << " Cycles: " << Cycles << endl;\r
+ cout << " IdleRPM: " << IdleRPM << endl;\r
+ cout << " MaxThrottle: " << MaxThrottle << endl;\r
+ cout << " MinThrottle: " << MinThrottle << endl;\r
+ cout << " SLFuelFlowMax: " << SLFuelFlowMax << endl;\r
+ }\r
+\r
+ Type = etPiston;\r
+ EngineNumber = 0; // FIXME: this should be the actual number\r
+ OilTemp_degK = 298; // FIXME: should be initialized in FGEngine\r
+\r
+ dt = State->Getdt();\r
+\r
+ // Initialisation\r
+ volumetric_efficiency = 0.8; // Actually f(speed, load) but this will get us running\r
+\r
+ // First column is thi, second is neta (combustion efficiency)\r
+ Lookup_Combustion_Efficiency = new FGTable(12);\r
+ *Lookup_Combustion_Efficiency << 0.00 << 0.980;\r
+ *Lookup_Combustion_Efficiency << 0.90 << 0.980;\r
+ *Lookup_Combustion_Efficiency << 1.00 << 0.970;\r
+ *Lookup_Combustion_Efficiency << 1.05 << 0.950;\r
+ *Lookup_Combustion_Efficiency << 1.10 << 0.900;\r
+ *Lookup_Combustion_Efficiency << 1.15 << 0.850;\r
+ *Lookup_Combustion_Efficiency << 1.20 << 0.790;\r
+ *Lookup_Combustion_Efficiency << 1.30 << 0.700;\r
+ *Lookup_Combustion_Efficiency << 1.40 << 0.630;\r
+ *Lookup_Combustion_Efficiency << 1.50 << 0.570;\r
+ *Lookup_Combustion_Efficiency << 1.60 << 0.525;\r
+ *Lookup_Combustion_Efficiency << 2.00 << 0.345;\r
+\r
+ cout << endl;\r
+ cout << " Combustion Efficiency table:" << endl;\r
+ Lookup_Combustion_Efficiency->Print();\r
+ cout << endl;\r
+\r
+ Power_Mixture_Correlation = new FGTable(13);\r
+ *Power_Mixture_Correlation << (14.7/1.6) << 78.0;\r
+ *Power_Mixture_Correlation << 10 << 86.0;\r
+ *Power_Mixture_Correlation << 11 << 93.5;\r
+ *Power_Mixture_Correlation << 12 << 98.0;\r
+ *Power_Mixture_Correlation << 13 << 100.0;\r
+ *Power_Mixture_Correlation << 14 << 99.0;\r
+ *Power_Mixture_Correlation << 15 << 96.4;\r
+ *Power_Mixture_Correlation << 16 << 92.5;\r
+ *Power_Mixture_Correlation << 17 << 88.0;\r
+ *Power_Mixture_Correlation << 18 << 83.0;\r
+ *Power_Mixture_Correlation << 19 << 78.5;\r
+ *Power_Mixture_Correlation << 20 << 74.0;\r
+ *Power_Mixture_Correlation << (14.7/0.6) << 58;\r
+\r
+ cout << endl;\r
+ cout << " Power Mixture Correlation table:" << endl;\r
+ Power_Mixture_Correlation->Print();\r
+ cout << endl;\r
+\r
+ if (debug_lvl & 2) cout << "Instantiated: FGPiston" << endl;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+FGPiston::~FGPiston()\r
+{\r
+ if (debug_lvl & 2) cout << "Destroyed: FGPiston" << endl;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+float FGPiston::Calculate(float PowerRequired)\r
+{\r
+ float h,EngineMaxPower;\r
+\r
+ // FIXME: calculate from actual fuel flow\r
+ ConsumeFuel();\r
+\r
+ Throttle = FCS->GetThrottlePos(EngineNumber);\r
+ Mixture = FCS->GetMixturePos(EngineNumber);\r
+\r
+ //\r
+ // Input values.\r
+ //\r
+\r
+ p_amb = Atmosphere->GetPressure() * 48; // convert from lbs/ft2 to Pa\r
+ p_amb_sea_level = Atmosphere->GetPressureSL() * 48;\r
+ T_amb = Atmosphere->GetTemperature() * (5.0 / 9.0); // convert from Rankine to Kelvin\r
+\r
+ RPM = Propulsion->GetThruster(EngineNumber)->GetRPM();\r
+ //if (RPM < IdleRPM) RPM = IdleRPM; // kludge\r
+ \r
+ IAS = Auxiliary->GetVcalibratedKTS();\r
+\r
+ if (Mixture >= 0.5) {\r
+ doEngineStartup();\r
+ doManifoldPressure();\r
+ doAirFlow();\r
+ doFuelFlow();\r
+ doEnginePower();\r
+ doEGT();\r
+ doCHT();\r
+ doOilTemperature();\r
+ doOilPressure();\r
+ } else {\r
+ HP = 0;\r
+ }\r
+\r
+ PowerAvailable = (HP * HPTOFTLBSSEC) - PowerRequired;\r
+ return PowerAvailable;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Start or stop the engine.\r
+ */\r
+\r
+void FGPiston::doEngineStartup(void)\r
+{\r
+ // TODO: check magnetos, spark, starter, etc. and decide whether\r
+ // engine is running\r
+\r
+ // Check parameters that may alter the operating state of the engine. \r
+ // (spark, fuel, starter motor etc)\r
+ bool spark;\r
+ bool fuel;\r
+ static int crank_counter = 0;\r
+\r
+ // Check for spark\r
+ Magneto_Left = false;\r
+ Magneto_Right = false;\r
+ // Magneto positions:\r
+ // 0 -> off\r
+ // 1 -> left only\r
+ // 2 -> right only\r
+ // 3 -> both\r
+ if (Magnetos != 0) {\r
+ spark = true;\r
+ } else {\r
+ spark = false;\r
+ } // neglects battery voltage, master on switch, etc for now.\r
+ \r
+ if ((Magnetos == 1) || (Magnetos > 2)) Magneto_Left = true;\r
+ if (Magnetos > 1) Magneto_Right = true;\r
+\r
+ // Assume we have fuel for now\r
+ fuel = true;\r
+\r
+ // Check if we are turning the starter motor\r
+ if (Cranking != Starter) {\r
+ // This check saves .../cranking from getting updated every loop - they\r
+ // only update when changed.\r
+ Cranking = Starter;\r
+ crank_counter = 0;\r
+ }\r
+\r
+ //Check mode of engine operation\r
+ // ACK - unfortunately this hack doesn't work in JSBSim since the RPM is reset\r
+ // each iteration by the propeller :-(\r
+ if (Cranking) {\r
+ crank_counter++;\r
+ if (RPM <= 480) {\r
+ RPM += 100;\r
+ if (RPM > 480)\r
+ RPM = 480;\r
+ } else {\r
+ // consider making a horrible noise if the starter is engaged with\r
+ // the engine running\r
+ }\r
+ // TODO - find a better guess at cranking speed\r
+ }\r
+ \r
+ // if ((!Running) && (spark) && (fuel) && (crank_counter > 120)) {\r
+\r
+ if ((!Running) && (spark) && (fuel)) {\r
+ // start the engine if revs high enough\r
+ if (RPM > 450) {\r
+ // For now just instantaneously start but later we should maybe crank for\r
+ // a bit\r
+ Running = true;\r
+ // RPM = 600;\r
+ }\r
+ }\r
+\r
+ if ( (Running) && ((!spark)||(!fuel)) ) {\r
+ // Cut the engine\r
+ // note that we only cut the power - the engine may continue to\r
+ // spin if the prop is in a moving airstream\r
+ Running = false;\r
+ }\r
+\r
+ // And finally a last check for stalling\r
+ if (Running) { \r
+ //Check if we have stalled the engine\r
+ if (RPM == 0) {\r
+ Running = false;\r
+ } else if ((RPM <= 480) && (Cranking)) {\r
+ // Make sure the engine noise dosn't play if the engine won't\r
+ // start due to eg mixture lever pulled out.\r
+ Running = false;\r
+ }\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+/**\r
+ * Calculate the nominal manifold pressure in inches hg\r
+ *\r
+ * This function calculates nominal manifold pressure directly\r
+ * from the throttle position, and does not adjust it for the\r
+ * difference between the pressure at sea level and the pressure\r
+ * at the current altitude (that adjustment takes place in\r
+ * {@link #doEnginePower}).\r
+ *\r
+ * TODO: changes in MP should not be instantaneous -- introduce\r
+ * a lag between throttle changes and MP changes, to allow pressure\r
+ * to build up or disperse.\r
+ *\r
+ * Inputs: MinManifoldPressure_inHg, MaxManifoldPressure_inHg, Throttle\r
+ *\r
+ * Outputs: ManifoldPressure_inHg\r
+ */\r
+\r
+void FGPiston::doManifoldPressure(void)\r
+{\r
+ ManifoldPressure_inHg = MinManifoldPressure_inHg +\r
+ (Throttle * (MaxManifoldPressure_inHg - MinManifoldPressure_inHg));\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the air flow through the engine.\r
+ *\r
+ * Inputs: p_amb, R_air, T_amb, ManifoldPressure_inHg, Displacement,\r
+ * RPM, volumetric_efficiency\r
+ *\r
+ * Outputs: rho_air, m_dot_air\r
+ */\r
+\r
+void FGPiston::doAirFlow(void)\r
+{\r
+ rho_air = p_amb / (R_air * T_amb);\r
+ float rho_air_manifold = rho_air * ManifoldPressure_inHg / 29.6;\r
+ float displacement_SI = Displacement * CONVERT_CUBIC_INCHES_TO_METERS_CUBED;\r
+ float swept_volume = (displacement_SI * (RPM/60)) / 2;\r
+ float v_dot_air = swept_volume * volumetric_efficiency;\r
+ m_dot_air = v_dot_air * rho_air_manifold;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the fuel flow into the engine.\r
+ *\r
+ * Inputs: Mixture, thi_sea_level, p_amb_sea_level, p_amb, m_dot_air\r
+ *\r
+ * Outputs: equivalence_ratio, m_dot_fuel\r
+ */\r
+\r
+void FGPiston::doFuelFlow(void)\r
+{\r
+ float thi_sea_level = 1.3 * Mixture;\r
+ equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb;\r
+ m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the power produced by the engine.\r
+ *\r
+ * <p>Currently, the JSBSim propellor model does not allow the\r
+ * engine to produce enough RPMs to get up to a high horsepower.\r
+ * When tested with sufficient RPM, it has no trouble reaching\r
+ * 200HP.</p>\r
+ *\r
+ * Inputs: ManifoldPressure_inHg, p_amb, p_amb_sea_level, RPM, T_amb, \r
+ * equivalence_ratio, Cycles, MaxHP\r
+ *\r
+ * Outputs: Percentage_Power, HP\r
+ */\r
+\r
+void FGPiston::doEnginePower(void)\r
+{\r
+ float True_ManifoldPressure_inHg = ManifoldPressure_inHg * p_amb / p_amb_sea_level;\r
+ float ManXRPM = True_ManifoldPressure_inHg * RPM;\r
+ // FIXME: this needs to be generalized\r
+ Percentage_Power = (6e-9 * ManXRPM * ManXRPM) + (8e-4 * ManXRPM) - 1.0;\r
+ float T_amb_degF = (T_amb * 1.8) - 459.67;\r
+ float T_amb_sea_lev_degF = (288 * 1.8) - 459.67; \r
+ Percentage_Power =\r
+ Percentage_Power + ((T_amb_sea_lev_degF - T_amb_degF) * 7 /120);\r
+ float Percentage_of_best_power_mixture_power =\r
+ Power_Mixture_Correlation->GetValue(14.7 / equivalence_ratio);\r
+ Percentage_Power =\r
+ Percentage_Power * Percentage_of_best_power_mixture_power / 100.0;\r
+ if (Percentage_Power < 0.0)\r
+ Percentage_Power = 0.0;\r
+ else if (Percentage_Power > 100.0)\r
+ Percentage_Power = 100.0;\r
+ HP = Percentage_Power * MaxHP / 100.0;\r
+\r
+ //Hack\r
+ if (!Running) {\r
+ if (Cranking) {\r
+ if (RPM < 480) {\r
+ HP = 3.0 + ((480 - RPM) / 10.0);\r
+ } else {\r
+ HP = 3.0;\r
+ }\r
+ } else {\r
+ // Quick hack until we port the FMEP stuff\r
+ if (RPM > 0.0)\r
+ HP = -1.5;\r
+ else\r
+ HP = 0.0;\r
+ }\r
+ }\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the exhaust gas temperature.\r
+ *\r
+ * Inputs: equivalence_ratio, m_dot_fuel, calorific_value_fuel, \r
+ * Cp_air, m_dot_air, Cp_fuel, m_dot_fuel, T_amb, Percentage_Power\r
+ *\r
+ * Outputs: combustion_efficiency, ExhaustGasTemp_degK\r
+ */\r
+\r
+void FGPiston::doEGT(void)\r
+{\r
+ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio);\r
+ float enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * \r
+ combustion_efficiency * 0.33;\r
+ float heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);\r
+ float delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust;\r
+ ExhaustGasTemp_degK = T_amb + delta_T_exhaust;\r
+ ExhaustGasTemp_degK *= 0.444 + ((0.544 - 0.444) * Percentage_Power / 100.0);\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the cylinder head temperature.\r
+ *\r
+ * Inputs: T_amb, IAS, rho_air, m_dot_fuel, calorific_value_fuel,\r
+ * combustion_efficiency, RPM\r
+ *\r
+ * Outputs: CylinderHeadTemp_degK\r
+ */\r
+\r
+void FGPiston::doCHT(void)\r
+{\r
+ float h1 = -95.0;\r
+ float h2 = -3.95;\r
+ float h3 = -0.05;\r
+\r
+ float arbitary_area = 1.0;\r
+ float CpCylinderHead = 800.0;\r
+ float MassCylinderHead = 8.0;\r
+\r
+ float temperature_difference = CylinderHeadTemp_degK - T_amb;\r
+ float v_apparent = IAS * 0.5144444;\r
+ float v_dot_cooling_air = arbitary_area * v_apparent;\r
+ float m_dot_cooling_air = v_dot_cooling_air * rho_air;\r
+ float dqdt_from_combustion = \r
+ m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;\r
+ float dqdt_forced = (h2 * m_dot_cooling_air * temperature_difference) + \r
+ (h3 * RPM * temperature_difference);\r
+ float dqdt_free = h1 * temperature_difference;\r
+ float dqdt_cylinder_head = dqdt_from_combustion + dqdt_forced + dqdt_free;\r
+ \r
+ float HeatCapacityCylinderHead = CpCylinderHead * MassCylinderHead;\r
+ \r
+ CylinderHeadTemp_degK = dqdt_cylinder_head / HeatCapacityCylinderHead;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the oil temperature.\r
+ *\r
+ * Inputs: Percentage_Power, running flag.\r
+ *\r
+ * Outputs: OilTemp_degK\r
+ */\r
+\r
+void FGPiston::doOilTemperature(void)\r
+{\r
+ float idle_percentage_power = 2.3; // approximately\r
+ float target_oil_temp; // Steady state oil temp at the current engine conditions\r
+ float time_constant; // The time constant for the differential equation\r
+\r
+ if (Running) {\r
+ target_oil_temp = 363;\r
+ time_constant = 500; // Time constant for engine-on idling.\r
+ if (Percentage_Power > idle_percentage_power) {\r
+ time_constant /= ((Percentage_Power / idle_percentage_power) / 10.0); // adjust for power \r
+ }\r
+ } else {\r
+ target_oil_temp = 298;\r
+ time_constant = 1000; // Time constant for engine-off; reflects the fact\r
+ // that oil is no longer getting circulated\r
+ }\r
+\r
+ float dOilTempdt = (target_oil_temp - OilTemp_degK) / time_constant;\r
+\r
+ OilTemp_degK += (dOilTempdt * dt);\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+/**\r
+ * Calculate the oil pressure.\r
+ *\r
+ * Inputs: RPM\r
+ *\r
+ * Outputs: OilPressure_psi\r
+ */\r
+\r
+void FGPiston::doOilPressure(void)\r
+{\r
+ float Oil_Press_Relief_Valve = 60; // FIXME: may vary by engine\r
+ float Oil_Press_RPM_Max = 1800; // FIXME: may vary by engine\r
+ float Design_Oil_Temp = 85; // FIXME: may vary by engine\r
+ // FIXME: WRONG!!! (85 degK???)\r
+ float Oil_Viscosity_Index = 0.25;\r
+\r
+ OilPressure_psi = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * RPM;\r
+\r
+ if (OilPressure_psi >= Oil_Press_Relief_Valve) {\r
+ OilPressure_psi = Oil_Press_Relief_Valve;\r
+ }\r
+\r
+ OilPressure_psi += (Design_Oil_Temp - OilTemp_degK) * Oil_Viscosity_Index;\r
+}\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+void FGPiston::Debug(void)\r
+{\r
+ //TODO: Add your source code here\r
+}\r
+\r
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
- Header: FGPiston.h
- Author: Jon S. Berndt
- Date started: 09/12/2000
-
- ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) --------------
-
- 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 Foundation, Inc., 59 Temple
- Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Further information about the GNU General Public License can also be found on
- the world wide web at http://www.gnu.org.
-
-HISTORY
---------------------------------------------------------------------------------
-09/12/2000 JSB Created
-10/01/2001 DPM Modified to use equations from Dave Luff's piston model.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES, and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-SENTRY
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#ifndef FGPISTON_H
-#define FGPISTON_H
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-INCLUDES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#include "FGEngine.h"
-#include "FGConfigFile.h"
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DEFINITIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-#define ID_PISTON "$Id$";
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-FORWARD DECLARATIONS
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-COMMENTS, REFERENCES, and NOTES
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-DOCUMENTATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-/** Models Dave Luff's engine model as ported into JSBSim by David Megginson.
- @author Jon S. Berndt (Engine framework code and framework-related mods)
- @author Dave Luff (engine operational code)
- @author David Megginson (porting and additional code)
- @version $Id$
- */
-
-/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-CLASS DECLARATION
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-
-class FGPiston : public FGEngine
-{
-public:
- /// Constructor
- FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg);
- /// Destructor
- ~FGPiston();
-
- float Calculate(float PowerRequired);
- float GetPowerAvailable(void) {return PowerAvailable;}
-
-private:
- float BrakeHorsePower;
- float SpeedSlope;
- float SpeedIntercept;
- float AltitudeSlope;
- float PowerAvailable;
-
- // timestep
- float dt;
-
- // engine state
- bool running;
- bool cranking;
-
- void doEngineStartup(void);
- void doManifoldPressure(void);
- void doAirFlow(void);
- void doFuelFlow(void);
- void doEnginePower(void);
- void doEGT(void);
- void doCHT(void);
- void doOilPressure(void);
- void doOilTemperature(void);
-
- //
- // constants
- //
- const float CONVERT_CUBIC_INCHES_TO_METERS_CUBED;
-
- const float R_air;
- const float rho_fuel; // kg/m^3
- const float calorific_value_fuel; // W/Kg (approximate)
- const float Cp_air; // J/KgK
- const float Cp_fuel; // J/KgK
-
- //
- // Configuration
- //
- float MinManifoldPressure_inHg; // Inches Hg
- float MaxManifoldPressure_inHg; // Inches Hg
- float Displacement; // cubic inches
- float MaxHP; // horsepower
- float Cycles; // cycles/power stroke
- float IdleRPM; // revolutions per minute
-
- //
- // Inputs (in addition to those in FGEngine).
- //
- float p_amb; // Pascals
- float p_amb_sea_level; // Pascals
- float T_amb; // degrees Kelvin
- float RPM; // revolutions per minute
- float IAS; // knots
-
- //
- // Outputs (in addition to those in FGEngine).
- //
- float rho_air;
- float volumetric_efficiency;
- float m_dot_air;
- float equivalence_ratio;
- float m_dot_fuel;
- float Percentage_Power;
- float HP;
- float combustion_efficiency;
-
- void Debug(void);
-};
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-#endif
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+ Header: FGPiston.h\r
+ Author: Jon S. Berndt\r
+ Date started: 09/12/2000\r
+\r
+ ------------- Copyright (C) 2000 Jon S. Berndt (jsb@hal-pc.org) --------------\r
+\r
+ This program is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License as published by the Free Software\r
+ Foundation; either version 2 of the License, or (at your option) any later\r
+ version.\r
+\r
+ This program is distributed in the hope that it will be useful, but WITHOUT\r
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details.\r
+\r
+ You should have received a copy of the GNU General Public License along with\r
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
+ Place - Suite 330, Boston, MA 02111-1307, USA.\r
+\r
+ Further information about the GNU General Public License can also be found on\r
+ the world wide web at http://www.gnu.org.\r
+\r
+HISTORY\r
+--------------------------------------------------------------------------------\r
+09/12/2000 JSB Created\r
+10/01/2001 DPM Modified to use equations from Dave Luff's piston model.\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+COMMENTS, REFERENCES, and NOTES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+SENTRY\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#ifndef FGPISTON_H\r
+#define FGPISTON_H\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+INCLUDES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#include "FGEngine.h"\r
+#include "FGConfigFile.h"\r
+#include "FGTable.h"\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+DEFINITIONS\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+#define ID_PISTON "$Id$";\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+FORWARD DECLARATIONS\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+COMMENTS, REFERENCES, and NOTES\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+DOCUMENTATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+/** Models Dave Luff's engine model as ported into JSBSim by David Megginson.\r
+ @author Jon S. Berndt (Engine framework code and framework-related mods)\r
+ @author Dave Luff (engine operational code)\r
+ @author David Megginson (porting and additional code)\r
+ @version $Id$\r
+ */\r
+\r
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+CLASS DECLARATION\r
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
+\r
+class FGPiston : public FGEngine\r
+{\r
+public:\r
+ /// Constructor\r
+ FGPiston(FGFDMExec* exec, FGConfigFile* Eng_cfg);\r
+ /// Destructor\r
+ ~FGPiston();\r
+\r
+ float Calculate(float PowerRequired);\r
+ float GetPowerAvailable(void) {return PowerAvailable;}\r
+\r
+private:\r
+ float BrakeHorsePower;\r
+ float SpeedSlope;\r
+ float SpeedIntercept;\r
+ float AltitudeSlope;\r
+ float PowerAvailable;\r
+\r
+ // timestep\r
+ float dt;\r
+\r
+ void doEngineStartup(void);\r
+ void doManifoldPressure(void);\r
+ void doAirFlow(void);\r
+ void doFuelFlow(void);\r
+ void doEnginePower(void);\r
+ void doEGT(void);\r
+ void doCHT(void);\r
+ void doOilPressure(void);\r
+ void doOilTemperature(void);\r
+\r
+ //\r
+ // constants\r
+ //\r
+ const float CONVERT_CUBIC_INCHES_TO_METERS_CUBED;\r
+\r
+ const float R_air;\r
+ const float rho_fuel; // kg/m^3\r
+ const float calorific_value_fuel; // W/Kg (approximate)\r
+ const float Cp_air; // J/KgK\r
+ const float Cp_fuel; // J/KgK\r
+\r
+ FGTable *Lookup_Combustion_Efficiency;\r
+ FGTable *Power_Mixture_Correlation;\r
+\r
+ //\r
+ // Configuration\r
+ //\r
+ float MinManifoldPressure_inHg; // Inches Hg\r
+ float MaxManifoldPressure_inHg; // Inches Hg\r
+ float Displacement; // cubic inches\r
+ float MaxHP; // horsepower\r
+ float Cycles; // cycles/power stroke\r
+ float IdleRPM; // revolutions per minute\r
+\r
+ //\r
+ // Inputs (in addition to those in FGEngine).\r
+ //\r
+ float p_amb; // Pascals\r
+ float p_amb_sea_level; // Pascals\r
+ float T_amb; // degrees Kelvin\r
+ float RPM; // revolutions per minute\r
+ float IAS; // knots\r
+\r
+ //\r
+ // Outputs (in addition to those in FGEngine).\r
+ //\r
+ bool Magneto_Left;\r
+ bool Magneto_Right;\r
+ float rho_air;\r
+ float volumetric_efficiency;\r
+ float m_dot_air;\r
+ float equivalence_ratio;\r
+ float m_dot_fuel;\r
+ float Percentage_Power;\r
+ float HP;\r
+ float combustion_efficiency;\r
+\r
+ void Debug(void);\r
+};\r
+\r
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
+#endif\r