2 // Author: Phil Schubert
3 // Date started: 12/03/99
4 // Purpose: Models a Continental IO-520-M Engine
5 // Called by: FGSimExec
7 // Copyright (C) 1999 Philip L. Schubert (philings@ozemail.com.au)
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License as
11 // published by the Free Software Foundation; either version 2 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 // Further information about the GNU General Public License can also
25 // be found on the world wide web at http://www.gnu.org.
27 // FUNCTIONAL DESCRIPTION
28 // ------------------------------------------------------------------------
29 // Models a Continental IO-520-M engine. This engine is used in Cessna
30 // 210, 310, Beechcraft Bonaza and Baron C55. The equations used below
31 // were determined by a first and second order curve fits using Excel.
32 // The data is from the Cessna Aircraft Corporations Engine and Flight
33 // Computer for C310. Part Number D3500-13
36 // ------------------------------------------------------------------------
40 // ------------------------------------------------------------------------
41 // 12/03/99 PLS Created
42 // 07/03/99 PLS Added Calculation of Density, and Prop_Torque
43 // 07/03/99 PLS Restructered Variables to allow easier implementation
45 // 15/03/99 PLS Added Oil Pressure, Oil Temperature and CH Temp
46 // ------------------------------------------------------------------------
48 // ------------------------------------------------------------------------
51 /////////////////////////////////////////////////////////////////////
53 // Modified by Dave Luff (david.luff@nottingham.ac.uk) September 2000
55 // Altered manifold pressure range to add a minimum value at idle to simulate the throttle stop / idle bypass valve,
56 // and to reduce the maximum value whilst the engine is running to slightly below ambient to account for CdA losses across the throttle
58 // Altered it a bit to model an IO360 from C172 - 360 cubic inches, 180 HP max, fixed pitch prop
59 // Added a simple fixed pitch prop model by Nev Harbor - this is not intended as a final model but simply a hack to get it running for now
60 // I used Phil's ManXRPM correlation for power rather than do a new one for the C172 for now, but altered it a bit to reduce power at the low end
62 // Added EGT model based on combustion efficiency and an energy balance with the exhaust gases
64 // Added a mixture - power correlation based on a curve in the IO360 operating manual
66 // I've tried to match the prop and engine model to give roughly 600 RPM idle and 180 HP at 2700 RPM
67 // but it is by no means currently at a completed stage - DCL 15/9/00
69 // DCL 28/9/00 - Added estimate of engine and prop inertia and changed engine speed calculation to be calculated from Angular acceleration = Torque / Inertia.
70 // Requires a timestep to be passed to FGEngine::init and currently assumes this timestep does not change.
71 // Could easily be altered to pass a variable timestep to FGEngine::update every step instead if required.
73 //////////////////////////////////////////////////////////////////////
82 // ------------------------------------------------------------------------
84 // ------------------------------------------------------------------------
87 // Calculate Engine RPM based on Propellor Lever Position
88 float FGEngine::Calc_Engine_RPM (float LeverPosition)
90 // Calculate RPM as set by Prop Lever Position. Assumes engine
91 // will run at 1000 RPM at full course
94 RPM = LeverPosition * Max_RPM / 100.0;
95 // * ((FGEng_Max_RPM + FGEng_Min_RPM) / 100);
97 if ( RPM >= Max_RPM ) {
104 float FGEngine::Lookup_Combustion_Efficiency(float thi_actual)
106 float thi[11]; //array of equivalence ratio values
107 float neta_comb[11]; //corresponding array of combustion efficiency values
108 float neta_comb_actual;
111 //thi = (0.0,0.9,1.0,1.05,1.1,1.15,1.2,1.3,1.4,1.5,1.6);
115 thi[3] = 1.05; //There must be an easier way of doing this !!!!!!!!
123 //neta_comb = (0.98,0.98,0.97,0.95,0.9,0.85,0.79,0.7,0.63,0.57,0.525);
134 neta_comb[10] = 0.525;
135 //combustion efficiency values from Heywood: ISBN 0-07-100499-8
139 j = 11; //This must be equal to the number of elements in the lookup table arrays
145 //this is just to avoid crashing the routine is we are bigger than the last element - for now just return the last element
146 //but at some point we will have to extrapolate further
147 neta_comb_actual = neta_comb[i];
148 return neta_comb_actual;
150 if(thi_actual == thi[i])
152 neta_comb_actual = neta_comb[i];
153 return neta_comb_actual;
155 if((thi_actual > thi[i]) && (thi_actual < thi[i + 1]))
157 //do linear interpolation between the two points
158 factor = (thi_actual - thi[i]) / (thi[i+1] - thi[i]);
159 neta_comb_actual = (factor * (neta_comb[i+1] - neta_comb[i])) + neta_comb[i];
160 return neta_comb_actual;
164 //if we get here something has gone badly wrong
165 cout << "ERROR: error in FGEngine::Lookup_Combustion_Efficiency\n";
167 return neta_comb_actual; //keeps the compiler happy
170 float FGEngine::Calculate_Delta_T_Exhaust(void)
173 heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);
174 dT_exhaust = enthalpy_exhaust / heat_capacity_exhaust;
180 // Calculate Manifold Pressure based on Throttle lever Position
181 static float Calc_Manifold_Pressure ( float LeverPosn, float MaxMan, float MinMan)
188 //Note that setting the manifold pressure as a function of lever position only is not strictly accurate
189 //MAP is also a function of engine speed.
190 Inches = MinMan + (LeverPosn * (MaxMan - MinMan) / 100);
192 //allow for idle bypass valve or slightly open throttle stop
200 // set initial default values
201 void FGEngine::init(double dt) {
203 CONVERT_CUBIC_INCHES_TO_METERS_CUBED = 1.638706e-5;
204 // Control and environment inputs
206 Throttle_Lever_Pos = 75;
207 Propeller_Lever_Pos = 75;
208 Mixture_Lever_Pos = 100;
209 Cp_air = 1005; // J/KgK
210 Cp_fuel = 1700; // J/KgK
211 calorific_value_fuel = 47.3e6; // W/Kg Note that this is only an approximate value
215 // Engine Specific Variables used by this program that have limits.
216 // Will be set in a parameter file to be read in to create
217 // and instance for each engine.
218 Max_Manifold_Pressure = 28.50; //Inches Hg. An approximation - should be able to find it in the engine performance data
219 Min_Manifold_Pressure = 6.5; //Inches Hg. This is a guess corresponding to approx 0.24 bar MAP (7 in Hg) - need to find some proper data for this
221 Min_RPM = 600; //Recommended idle from Continental data sheet
223 Mag_Derate_Percent = 5;
224 // MaxHP = 285; //Continental IO520-M
225 MaxHP = 180; //Lycoming IO360
226 // displacement = 520; //Continental IO520-M
227 displacement = 360; //Lycoming IO360
228 engine_inertia = 0.2; //kgm^2 - value taken from a popular family saloon car engine - need to find an aeroengine value !!!!!
229 prop_inertia = 0.03; //kgm^2 - this value is a total guess - dcl
230 displacement_SI = displacement * CONVERT_CUBIC_INCHES_TO_METERS_CUBED;
236 CONVERT_HP_TO_WATTS = 745.6999;
238 // outfile.open(ios::out|ios::trunc);
240 // Initialise Engine Variables used by this instance
241 Percentage_Power = 0;
242 Manifold_Pressure = 29.00; // Inches
244 Fuel_Flow = 0; // lbs/hour
248 Oil_Pressure = 0; // PSI
249 Oil_Temp = 85; // Deg C
252 Torque_Imbalance = 0;
253 Desired_RPM = 2500; //Recommended cruise RPM from Continental datasheet
255 // Initialise Propellor Variables used by this instance
256 FGProp1_Angular_V = 0;
257 FGProp1_Coef_Drag = 0.6;
261 FGProp1_Coef_Lift = 0.1;
263 FGProp1_Blade_Angle = 13.5;
264 FGProp_Fine_Pitch_Stop = 13.5;
266 // Other internal values
271 // Calculate Oil Pressure
272 static float Oil_Press (float Oil_Temp, float Engine_RPM)
274 float Oil_Pressure = 0; //PSI
275 float Oil_Press_Relief_Valve = 60; //PSI
276 float Oil_Press_RPM_Max = 1800;
277 float Design_Oil_Temp = 85; //Celsius
278 float Oil_Viscosity_Index = 0.25; // PSI/Deg C
279 float Temp_Deviation = 0; // Deg C
281 Oil_Pressure = (Oil_Press_Relief_Valve / Oil_Press_RPM_Max) * Engine_RPM;
283 // Pressure relief valve opens at Oil_Press_Relief_Valve PSI setting
284 if (Oil_Pressure >= Oil_Press_Relief_Valve)
286 Oil_Pressure = Oil_Press_Relief_Valve;
289 // Now adjust pressure according to Temp which affects the viscosity
291 Oil_Pressure += (Design_Oil_Temp - Oil_Temp) * Oil_Viscosity_Index;
297 // Calculate Cylinder Head Temperature
298 static float Calc_CHT (float Fuel_Flow, float Mixture, float IAS)
306 //Calculate Exhaust Gas Temperature
307 //For now we will simply adjust this as a function of mixture
308 //It may be necessary to consider fuel flow rates and CHT in the calculation in the future
309 static float Calc_EGT (float Mixture)
311 float EGT = 1000; //off the top of my head !!!!
312 //Now adjust for mixture strength
318 // Calculate Density Ratio
319 static float Density_Ratio ( float x )
322 y = ((3E-10 * x * x) - (3E-05 * x) + 0.9998);
327 // Calculate Air Density - Rho
328 static float Density ( float x )
331 y = ((9E-08 * x * x) - (7E-08 * x) + 0.0024);
336 // Calculate Speed in FPS given Knots CAS
337 static float IAS_to_FPS (float x)
345 // update the engine model based on current control positions
346 void FGEngine::update() {
347 // Declare local variables
349 // const int num2 = 500; // default is 100, number if iterations to run
350 const int num2 = 5; // default is 100, number if iterations to run
356 // Set up the new variables
357 float Blade_Station = 30;
358 float FGProp_Area = 1.405/3;
359 float PI = 3.1428571;
363 // 0 = Closed, 100 = Fully Open
364 // float Throttle_Lever_Pos = 75;
365 // 0 = Full Course 100 = Full Fine
366 // float Propeller_Lever_Pos = 75;
367 // 0 = Idle Cut Off 100 = Full Rich
368 // float Mixture_Lever_Pos = 100;
370 // Environmental Variables
372 // Temp Variation from ISA (Deg F)
373 float FG_ISA_VAR = 0;
374 // Pressure Altitude 1000's of Feet
375 float FG_Pressure_Ht = 0;
377 // Parameters that alter the operation of the engine.
378 // Yes = 1. Is there Fuel Available. Calculated elsewhere
379 int Fuel_Available = 1;
380 // Off = 0. Reduces power by 3 % for same throttle setting
381 int Alternate_Air_Pos =0;
382 // 1 = On. Reduces power by 5 % for same power lever settings
383 int Magneto_Left = 1;
384 // 1 = On. Ditto, Both of the above though do not alter fuel flow
385 int Magneto_Right = 1;
387 // There needs to be a section in here to trap silly values, like
388 // 0, otherwise they will crash the calculations
390 // cout << " Number of Iterations ";
394 // cout << " Throttle % ";
395 // cin >> Throttle_Lever_Pos;
398 // cout << " Prop % ";
399 // cin >> Propeller_Lever_Pos;
402 //==================================================================
403 // Engine & Environmental Inputs from elsewhere
405 // Calculate Air Density (Rho) - In FG this is calculated in
408 Rho = Density(FG_Pressure_Ht); // In FG FG_Pressure_Ht is "h"
409 // cout << "Rho = " << Rho << endl;
411 // Calculate Manifold Pressure (Engine 1) as set by throttle opening
414 Calc_Manifold_Pressure( Throttle_Lever_Pos, Max_Manifold_Pressure, Min_Manifold_Pressure );
415 // cout << "manifold pressure = " << Manifold_Pressure << endl;
417 //DCL - hack for testing - fly at sea level
420 p_amb_sea_level = 101325;
422 //DCL - next calculate m_dot_air and m_dot_fuel into engine
424 //calculate actual ambient pressure and temperature from altitude
425 //Then find the actual manifold pressure (the calculated one is the sea level pressure)
426 True_Manifold_Pressure = Manifold_Pressure * p_amb / p_amb_sea_level;
428 // RPM = Calc_Engine_RPM(Propeller_Lever_Pos);
430 // cout << "Initial engine RPM = " << RPM << endl;
432 // Desired_RPM = RPM;
436 //DCL - calculate mass air flow into engine based on speed and load - separate this out into a function eventually
437 //t_amb is actual temperature calculated from altitude
438 //calculate density from ideal gas equation
439 rho_air = p_amb / ( R_air * T_amb );
440 rho_air_manifold = rho_air * Manifold_Pressure / 29.6;
441 //calculate ideal engine volume inducted per second
442 swept_volume = (displacement_SI * (RPM / 60)) / 2; //This equation is only valid for a four stroke engine
443 //calculate volumetric efficiency - for now we will just use 0.8, but actually it is a function of engine speed and the exhaust to manifold pressure ratio
444 volumetric_efficiency = 0.8;
445 //Now use volumetric efficiency to calculate actual air volume inducted per second
446 v_dot_air = swept_volume * volumetric_efficiency;
447 //Now calculate mass flow rate of air into engine
448 m_dot_air = v_dot_air * rho_air_manifold;
450 // cout << "rho air manifold " << rho_air_manifold << '\n';
451 // cout << "Swept volume " << swept_volume << '\n';
455 //DCL - now calculate fuel flow into engine based on air flow and mixture lever position
456 //assume lever runs from no flow at fully out to thi = 1.6 at fully in at sea level
457 //also assume that the injector linkage is ideal - hence the set mixture is maintained at a given altitude throughout the speed and load range
458 thi_sea_level = 1.6 * ( Mixture_Lever_Pos / 100.0 );
459 equivalence_ratio = thi_sea_level * p_amb_sea_level / p_amb; //ie as we go higher the mixture gets richer for a given lever position
460 m_dot_fuel = m_dot_air / 14.7 * equivalence_ratio;
462 // cout << "fuel " << m_dot_fuel;
463 // cout << " air " << m_dot_air << '\n';
467 // cout << "Thi = " << equivalence_ratio << '\n';
469 combustion_efficiency = Lookup_Combustion_Efficiency(equivalence_ratio); //The combustion efficiency basically tells us what proportion of the fuels calorific value is released
471 // cout << "Combustion efficiency = " << combustion_efficiency << '\n';
473 //now calculate energy release to exhaust
474 //We will assume a three way split of fuel energy between useful work, the coolant system and the exhaust system
475 //This is a reasonable first suck of the thumb estimate for a water cooled automotive engine - whether it holds for an air cooled aero engine is probably open to question
476 //Regardless - it won't affect the variation of EGT with mixture, and we con always put a multiplier on EGT to get a reasonable peak value.
477 enthalpy_exhaust = m_dot_fuel * calorific_value_fuel * combustion_efficiency * 0.33;
478 heat_capacity_exhaust = (Cp_air * m_dot_air) + (Cp_fuel * m_dot_fuel);
479 delta_T_exhaust = enthalpy_exhaust / heat_capacity_exhaust;
480 // delta_T_exhaust = Calculate_Delta_T_Exhaust();
482 // cout << "T_amb " << T_amb;
483 // cout << " dT exhaust = " << delta_T_exhaust;
485 EGT = T_amb + delta_T_exhaust;
487 // cout << " EGT = " << EGT << '\n';
490 // Calculate Manifold Pressure (Engine 2) as set by throttle opening
492 // FGEng2_Manifold_Pressure = Manifold_Pressure(FGEng2_Throttle_Lever_Pos, FGEng2_Manifold_Pressure);
493 // Show_Manifold_Pressure(FGEng2_Manifold_Pressure);
497 //==================================================================
498 // Engine Power & Torque Calculations
500 // Loop until stable - required for testing only
501 // for (num = 0; num < num2; num++) {
502 // cout << Manifold_Pressure << " Inches" << "\t";
503 // cout << RPM << " RPM" << "\t";
505 // For a given Manifold Pressure and RPM calculate the % Power
506 // Multiply Manifold Pressure by RPM
507 ManXRPM = Manifold_Pressure * RPM;
511 // Phil's %power correlation
512 /* // Calculate % Power
513 Percentage_Power = (+ 7E-09 * ManXRPM * ManXRPM)
514 + ( + 7E-04 * ManXRPM) - 0.1218;
515 // cout << Percentage_Power << "%" << "\t"; */
517 // DCL %power correlation - basically Phil's correlation modified to give slighty less power at the low end
518 // might need some adjustment as the prop model is adjusted
519 // My aim is to match the prop model and engine model at the low end to give the manufacturer's recommended idle speed with the throttle closed - 600rpm for the Continental IO520
521 Percentage_Power = (+ 6E-09 * ManXRPM * ManXRPM)
522 + ( + 8E-04 * ManXRPM) - 1.8524;
523 // cout << Percentage_Power << "%" << "\t";
525 // Adjust for Temperature - Temperature above Standard decrease
526 // power % by 7/120 per degree F increase, and incease power for
527 // temps below at the same ratio
528 Percentage_Power = Percentage_Power - (FG_ISA_VAR * 7 /120);
529 // cout << Percentage_Power << "%" << "\t";
531 // Adjust for Altitude. In this version a linear variation is
532 // used. Decrease 1% for each 1000' increase in Altitde
533 Percentage_Power = Percentage_Power + (FG_Pressure_Ht * 12/10000);
534 // cout << Percentage_Power << "%" << "\t";
536 //DCL - now adjust power to compensate for mixture
537 //uses a curve fit to the data in the IO360 / O360 operating manual
538 //due to the shape of the curve I had to use a 6th order fit - I am sure it must be possible to reduce this in future,
539 //possibly by using separate fits for rich and lean of best power mixture
540 //first adjust actual mixture to abstract mixture - this is a temporary hack in order to account for the fact that the data I have
541 //dosn't specify actual mixtures and I want to be able to change what I think they are without redoing the curve fit each time.
543 abstract_mixture = 10.0 * equivalence_ratio - 12.0;
544 float m = abstract_mixture; //to simplify writing the next equation
545 Percentage_of_best_power_mixture_power = ((-0.0012*m*m*m*m*m*m) + (0.021*m*m*m*m*m) + (-0.1425*m*m*m*m) + (0.4395*m*m*m) + (-0.8909*m*m) + (-0.5155*m) + 100.03);
546 Percentage_Power = Percentage_Power * Percentage_of_best_power_mixture_power / 100.0;
549 // Now Calculate Fuel Flow based on % Power Best Power Mixture
550 Fuel_Flow = Percentage_Power * Max_Fuel_Flow / 100.0;
551 // cout << Fuel_Flow << " lbs/hr"<< endl;
553 // Now Derate engine for the effects of Bad/Switched off magnetos
554 if (Magneto_Left == 0 && Magneto_Right == 0) {
555 // cout << "Both OFF\n";
556 Percentage_Power = 0;
557 } else if (Magneto_Left && Magneto_Right) {
558 // cout << "Both On ";
559 } else if (Magneto_Left == 0 || Magneto_Right== 0) {
560 // cout << "1 Magneto Failed ";
562 Percentage_Power = Percentage_Power *
563 ((100.0 - Mag_Derate_Percent)/100.0);
564 // cout << FGEng1_Percentage_Power << "%" << "\t";
567 // Calculate Engine Horsepower
569 HP = Percentage_Power * MaxHP / 100.0;
571 Power_SI = HP * CONVERT_HP_TO_WATTS;
573 // Calculate Engine Torque
575 Torque = HP * 5252 / RPM;
576 // cout << Torque << "Ft/lbs" << "\t";
578 Torque_SI = (Power_SI * 60.0) / (2.0 * PI * RPM); //Torque = power / angular velocity
579 // cout << Torque << " Nm\n";
581 // Calculate Cylinder Head Temperature
582 CHT = Calc_CHT( Fuel_Flow, Mixture, IAS);
583 // cout << "Cylinder Head Temp (F) = " << CHT << endl;
585 // EGT = Calc_EGT( Mixture );
587 // Calculate Oil Pressure
588 Oil_Pressure = Oil_Press( Oil_Temp, RPM );
589 // cout << "Oil Pressure (PSI) = " << Oil_Pressure << endl;
591 //==============================================================
593 // Now do the Propellor Calculations
595 #ifdef PHILS_PROP_MODEL
598 FGProp1_RPS = RPM * Gear_Ratio / 60.0;
599 // cout << FGProp1_RPS << " RPS" << endl;
601 //Radial Flow Vector (V2) Ft/sec at Ref Blade Station (usually 30")
602 FGProp1_Angular_V = FGProp1_RPS * 2 * PI * (Blade_Station / 12);
603 // cout << FGProp1_Angular_V << "Angular Velocity " << endl;
605 // Axial Flow Vector (Vo) Ft/sec
606 // Some further work required here to allow for inflow at low speeds
607 // Vo = (IAS + 20) * 1.688888;
608 Vo = IAS_to_FPS(IAS + 20);
609 // cout << "Feet/sec = " << Vo << endl;
611 // cout << Vo << "Axial Velocity" << endl;
613 // Relative Velocity (V1)
614 V1 = sqrt((FGProp1_Angular_V * FGProp1_Angular_V) +
616 // cout << V1 << "Relative Velocity " << endl;
618 // cout << FGProp1_Blade_Angle << " Prop Blade Angle" << endl;
620 // Blade Angle of Attack (Alpha1)
622 /* cout << " Alpha1 = " << Alpha1
623 << " Blade angle = " << FGProp1_Blade_Angle
625 << " FGProp1_Angular_V = " << FGProp1_Angular_V << endl;*/
626 Alpha1 = FGProp1_Blade_Angle -(atan(Vo / FGProp1_Angular_V) * (180/PI));
627 // cout << Alpha1 << " Alpha1" << endl;
629 // Calculate Coefficient of Drag at Alpha1
630 FGProp1_Coef_Drag = (0.0005 * (Alpha1 * Alpha1)) + (0.0003 * Alpha1)
632 // cout << FGProp1_Coef_Drag << " Coef Drag" << endl;
634 // Calculate Coefficient of Lift at Alpha1
635 FGProp1_Coef_Lift = -(0.0026 * (Alpha1 * Alpha1)) + (0.1027 * Alpha1)
637 // cout << FGProp1_Coef_Lift << " Coef Lift " << endl;
639 // Covert Alplha1 to Radians
640 // Alpha1 = Alpha1 * PI / 180;
642 // Calculate Prop Torque
643 FGProp1_Torque = (0.5 * Rho * (V1 * V1) * FGProp_Area
644 * ((FGProp1_Coef_Lift * sin(Alpha1 * PI / 180))
645 + (FGProp1_Coef_Drag * cos(Alpha1 * PI / 180))))
646 * (Blade_Station/12);
647 // cout << FGProp1_Torque << " Prop Torque" << endl;
649 // Calculate Prop Thrust
650 // cout << " V1 = " << V1 << " Alpha1 = " << Alpha1 << endl;
651 FGProp1_Thrust = 0.5 * Rho * (V1 * V1) * FGProp_Area
652 * ((FGProp1_Coef_Lift * cos(Alpha1 * PI / 180))
653 - (FGProp1_Coef_Drag * sin(Alpha1 * PI / 180)));
654 // cout << FGProp1_Thrust << " Prop Thrust " << endl;
656 // End of Propeller Calculations
657 //==============================================================
659 #endif //PHILS_PROP_MODEL
661 #ifdef NEVS_PROP_MODEL
666 number_of_blades = 2.0;
668 allowance_for_spinner = blade_length / 12.0;
669 prop_fudge_factor = 1.453401525;
670 forward_velocity = IAS;
679 angular_velocity_SI = 2.0 * PI * RPM / 60.0;
681 allowance_for_spinner = blade_length / 12.0;
682 //Calculate thrust and torque by summing the contributions from each of the blade elements
683 //Assumes equal length elements with numbered 1 inboard -> num_elements outboard
687 // outfile << "Rho = " << Rho << '\n\n';
688 // outfile << "Drag = ";
689 for(i=1;i<=num_elements;i++)
692 distance = (blade_length * (element / num_elements)) + allowance_for_spinner;
693 element_drag = 0.5 * rho_air * ((distance * angular_velocity_SI)*(distance * angular_velocity_SI)) * (0.000833 * ((theta[int(element-1)] - (atan(forward_velocity/(distance * angular_velocity_SI))))*(theta[int(element-1)] - (atan(forward_velocity/(distance * angular_velocity_SI))))))
694 * (0.1 * (blade_length / element)) * number_of_blades;
696 element_lift = 0.5 * rho_air * ((distance * angular_velocity_SI)*(distance * angular_velocity_SI)) * (0.036 * (theta[int(element-1)] - (atan(forward_velocity/(distance * angular_velocity_SI))))+0.4)
697 * (0.1 * (blade_length / element)) * number_of_blades;
698 element_torque = element_drag * distance;
699 prop_torque += element_torque;
700 prop_thrust += element_lift;
701 // outfile << "Drag = " << element_drag << " n = " << element << '\n';
706 // outfile << "Angular velocity = " << angular_velocity_SI << " rad/s\n";
708 // cout << "Thrust = " << prop_thrust << '\n';
709 prop_thrust *= prop_fudge_factor;
710 prop_torque *= prop_fudge_factor;
711 prop_power_consumed_SI = prop_torque * angular_velocity_SI;
712 prop_power_consumed_HP = prop_power_consumed_SI / 745.699;
715 #endif //NEVS_PROP_MODEL
719 #ifdef PHILS_PROP_MODEL //Do Torque calculations in Ft/lbs - yuk :-(((
720 Torque_Imbalance = FGProp1_Torque - Torque;
722 if (Torque_Imbalance > 5) {
724 // FGProp1_RPM -= 25;
725 // FGProp1_Blade_Angle -= 0.75;
728 if (Torque_Imbalance < -5) {
730 // FGProp1_RPM += 25;
731 // FGProp1_Blade_Angle += 0.75;
736 #ifdef NEVS_PROP_MODEL //use proper units - Nm
737 Torque_Imbalance = Torque_SI - prop_torque; //This gives a +ve value when the engine torque exeeds the prop torque
739 angular_acceleration = Torque_Imbalance / (engine_inertia + prop_inertia);
740 angular_velocity_SI += (angular_acceleration * time_step);
741 RPM = (angular_velocity_SI * 60) / (2.0 * PI);
747 if( RPM > (Desired_RPM + 2)) {
748 FGProp1_Blade_Angle += 0.75; //This value could be altered depending on how far from the desired RPM we are
751 if( RPM < (Desired_RPM - 2)) {
752 FGProp1_Blade_Angle -= 0.75;
755 if (FGProp1_Blade_Angle < FGProp_Fine_Pitch_Stop) {
756 FGProp1_Blade_Angle = FGProp_Fine_Pitch_Stop;
763 //end constant speed prop
766 //DCL - stall the engine if RPM drops below 550 - this is possible if mixture lever is pulled right out
770 // outfile << "RPM = " << RPM << " Blade angle = " << FGProp1_Blade_Angle << " Engine torque = " << Torque << " Prop torque = " << FGProp1_Torque << '\n';
771 // outfile << "RPM = " << RPM << " Engine torque = " << Torque_SI << " Prop torque = " << prop_torque << '\n';
773 // cout << FGEng1_RPM << " Blade_Angle " << FGProp1_Blade_Angle << endl << endl;
777 // cout << "Final engine RPM = " << RPM << '\n';
785 // Calculate Oil Temperature
787 static float Oil_Temp (float Fuel_Flow, float Mixture, float IAS)