Aircraft Design Recipes in Python – User’s Guide¶
Welcome to ADRpy, a free library of aircraft design and performance analysis tools suitable for rapid sizing calculations. The models implemented in ADRpy are largely analytical, enabling fast explorations of large design spaces. Most of the methods can already be used in the earliest phases of the design process, even before a geometry model is built. In fact, ADRpy can serve as the basis of sensitivity analyses and uncertainty quantification (UQ) exercises as part of the analysis of the feasibility of the design requirements.
The classes, methods and functions of the library fall into three broad categories:
1. Models of the operating environment. These live in the Atmospheres module and include virtual atmospheres (ISA, MILHDBK310, etc.), runway models (suitable for takeoff and landing performance modelling using a ‘real world’ runway database) and models of propulsion performance response to variations in ambient conditions.
2. Conceptual sizing methods for fixed wing aircraft sizing (wing area and thrust/power requirements), given a set of constraints, such as takeoff distance, climb rate, etc. These can be found in the Constraint Analysis Module.
3. Utilities, including a module for Unit Conversions and a set of Miscellaneous Utilities.
This document contains numerous usage examples and details on the inputs and outputs of each class, method and function. You can copy and paste these into .py files and execute those in a development environment or from Python’s command prompt, you can copy and paste them line by line into a Python terminal or (perhaps most usefully) into a Jupyter notebook. Any problems, issues, questions, please raise an issue on GitHub. Happy designing!
Installing and running ADRpy¶
ADRpy is written in Python 3 and tested in Python 3.4, 3.5, 3.5dev, 3.6, 3.6dev and 3.7dev. It is not available for Python 2.
First and foremost, you will need to have Python installed  you can get the latest version here or as part of a number of alternative packages.
Once you have Python, on most systems you should be able to simply open an operating system terminal
and at the command prompt type python m pip install ADRpy
or just pip install ADRpy
(pip
is a Python package; in the unlikely event that it is not available on your system,
download getpip.py and run it by
entering python getpip.py
at the operating system prompt).
For the ADRpy source code, license conditions (GPLv3), and alternative installation instructions see the ADRpy GitHub repository.
Notebooks¶
ADRpy includes a library of examples recorded in Jupyter notebooks. You can play with these ‘live’ in Binder:
…or you can click File / Download as / … to create your own local copy in any number of formats. [Note: if you don’t want to wait for Binder to generate the library, you can still access the ‘static’ versions of the notebooks through nbviewer  click on the required notebook in the lower half of the holding page.]
ADRpy Modules¶
Atmospheres¶
This module contains tools for defining the environment in which aircraft performance analyses, tradeoff studies, conceptual sizing and other aircraft engineering calculations can be carried out.
The module contains the following class definitions:
Runway
Definition of a runway object, including the capability to instantiate a runway from a ‘real world’ database of the world’s airports.
Atmosphere
Definition of a virtual atmosphere object. This includes a number of methods that allow the user to query parameters of the atmosphere.
Obsprofile
Definition of an atmospheric observation (sounding) object. This allows the user to create bespoke atmospheres and any other atmospheres derived from specified temperature, pressure, etc. profiles (such as the MIL HDBK 310 atmospheres).
See, in what follows, detailed descriptions of these classes, their methods, functions, as well as usage examples.

class
atmospheres.
Atmosphere
(offset_deg=0, profile=None)¶ Standard or offstandard/custom atmospheres.
Available atmosphere types
1. The International Standard Atmosphere (ISA) model. Based on ESDU Data Item 77022, “Equations for calculation of International Standard Atmosphere and associated offstandard atmospheres”, published in 1977, amended in 2008. It covers the first 50km of the atmosphere.
Offstandard, temperature offset versions of the above.
3. Extremely warm/cold, and low/high density atmospheres from US MIL HDBK 310
Userdefined atmospheres based on interpolated data.
Example
from ADRpy import atmospheres as at from ADRpy import unitconversions as co # Instantiate an atmosphere object: an offstandard ISA # with a 10C offset isa_minus10 = at.Atmosphere(offset_deg=10) # Query altitude altitude_ft = 38000 altitude_m = co.feet2m(altitude_ft) # Query the ambient density in this model at the specified altitude print("ISA10C density at", str(altitude_ft), "feet (geopotential):", isa_minus10.airdens_kgpm3(altitude_m), "kg/m^3") # Query the speed of sound in this model at the specified altitude print("ISA10C speed of sound at", str(altitude_ft), "feet (geopotential):", isa_minus10.vsound_mps(altitude_m), "m/s")
Output:
ISA10C density at 38000 feet (geopotential): 0.348049478999 kg/m^3 ISA10C speed of sound at 38000 feet (geopotential): 288.1792251702055 m/s
Note
The unit tests (found in tests/t_atmospheres.py in the GitHub repository) compare the atmosphere outputs against data from the 1976 US Standard Atmosphere, NASATMX74335. ESDU 77022 describes its ISA model as being identical for all practical purposes with the US Standard Atmospheres.
Methods

airdens_kgpm3
(altitudes_m=0)¶ Ambient density in the current atmosphere in \(\mathrm{kg/m}^3\).

airpress_mbar
(altitudes_m=0)¶ Air pressure in mbar.

airpress_pa
(altitudes_m=0)¶ Pressures in the selected atmosphere, in Pa.

airtemp_c
(altitudes_m=0)¶ Air temperature in Celsius.

airtemp_k
(altitudes_m=0)¶ Temperatures in the selected atmosphere, in K.
Parameter:
 altitudes_m
altitudes at which the temperature is to be interrogated (float or array of floats)
Output:
Ambient temperature (Static Air Temperature) in Kelvin.
Example
from ADRpy import atmospheres as at isa = at.Atmosphere() print("ISA temperatures at SL, 5km, 10km (geopotential):", isa.airtemp_k([0, 5000, 10000]), "K")
Output:
ISA temperatures at SL, 5km, 10km (geopotential): [ 288.15 255.65 223.15] K

dynamicpressure_pa
(airspeed_mps=0, altitudes_m=0)¶ Dynamic pressure in the current atmosphere at a given true airspeed and altitude
Parameters
 airspeed_mps
float, true airspeed in m/s (MPSTAS)
 altitudes_m
float array, altitudes in m where the dynamic pressure is to be computed
Returns
float or array of floats, dynamic pressure values
Example
from ADRpy import atmospheres as at from ADRpy import unitconversions as co ISA = at.Atmosphere() altitudelist_m = [0, 500, 1000, 1500] MPSTAS = 20 q_Pa = ISA.dynamicpressure_pa(MPSTAS, altitudelist_m) q_mbar = co.pa2mbar(q_Pa) print(q_mbar)
Output:
[ 2.44999974 2.33453737 2.22328473 2.11613426]

eas2tas
(eas, altitude_m)¶ Converts EAS to TAS at a given altitude.
The method first calculates the density ratio \(\sigma\) (as the ratio of the ambient density at altitude_m and at the ambient density at sea level); the true airspeed is then calculated as:
\[\mathrm{TAS}=\frac{\mathrm{EAS}}{\sqrt{\sigma}}\]Parameters
 eas
Float or numpy array of floats. Equivalent airspeed (any unit, returned TAS value will be in the same unit).abs
 altitude_m
Float. Flight altitude in metres.
Returns
True airspeed in the same units as the EAS input.

keas2kcas
(keas, altitude_m)¶ Converts equivalent airspeed into calibrated airspeed.
The relationship between the two depends on the Mach number \(M\) and the ratio \(\delta\) of the pressure at the current altitude \(P_\mathrm{alt}\) and the sea level pressure \(P_\mathrm{0}\). We approximate this relationship with the expression:
\[\mathrm{CAS}\approx\mathrm{EAS}\left[1 + \frac{1}{8}(1\delta)M^2 + \frac{3}{640}\left(110\delta+9\delta^2 \right)M^4 \right]\]Parameters
 keas
float or numpy array, equivalent airspeed in knots.
 altitude_m
float, altitude in metres.
Returns
 kcas
float or numpy array, calibrated airspeed in knots.
 mach
float, Mach number.
See also
mpseas2mpscas
Notes
The reverse conversion is slightly more complicated, as their relationship depends on the Mach number. This, in turn, requires the computation of the true airspeed and that can only be computed from EAS, not CAS. The unit specific nature of the function is also the result of the need for computing the Mach number.
Example
import numpy as np from ADRpy import atmospheres as at from ADRpy import unitconversions as co isa = at.Atmosphere() keas = np.array([100, 200, 300]) altitude_m = co.feet2m(40000) kcas, mach = isa.keas2kcas(keas, altitude_m) print(kcas)
Output:
[ 101.25392563 209.93839073 333.01861569]

mach
(airspeed_mps, altitude_m=0)¶ Mach number at a given speed (m/s) and altitude (m)

mpseas2mpscas
(mpseas, altitude_m)¶ Convert EAS (m/s) to CAS (m/s) at a given altitude (m)

tas2eas
(tas, altitude_m)¶ Convert TAS to EAS at a given altitude

vsound_kts
(altitudes_m=0)¶ Speed of sound in knots.

vsound_mps
(altitudes_m=0)¶ Speed of sound in m/s at an altitude given in m.

class
atmospheres.
Obsprofile
(alt_m=None, temp_k=None, rho_kgpm3=None, p_pa=None)¶ Observed atmosphere profile data.

hialt
()¶ The maximum valid altitude (in m) of the interpolators.

loalt
()¶ The minimum valid altitude (in m) of the interpolators.


class
atmospheres.
Runway
(icao_code=None, rwyno=0, elevation_ft=0, heading=0, surf='ASP', length_ft=10000, width_ft=100)¶ Runway model to be used for takeoff/landing performance calculations.
Parameters (all optional):
 icao_code
String. International Civil Aviation Organisation code of the airport. Required if the user wishes to equip this object with the attributes of a specific, existing runway, e.g., ‘EGLL’ (London Heathrow airport). Runway data is obtained from an offline image of the ourairports.com database.
 rwyno
Integer. Specifies which of the runways at the airport specified by the ICAO code above we want to associate with the runway object. A ValueError will be thrown if rwyno exceeds the number of runways at the airport specified by the icao_code. The number of runways can be found in the nrways attribute of the runway object:
runway = at.Runway('KDEN') runway.nrways
Output:
6
 elevation_ft, heading, surf, length_ft, width_ft
Parameters of bespoke, userdefined runways. The recommended use of these is as indicated by their names, though the user may wish to adopt their own definitions to suit particular applications (for example, surf can be any string describing the runway surface).
Example  creating and querying a Runway class object:
from ADRpy import atmospheres as at runway = at.Runway('EGLL', 0) print('Runway: ', runway.le_ident, '/', runway.he_ident) print('True headings: ', runway.le_heading_degt, '/', runway.he_heading_degt, 'degrees') print('Elevation (low end): ', runway.le_elevation_ft, 'ft') print('Length: ', runway.length_ft, 'ft')
Outputs:
Runway: 09L / 27R True headings: 89.6 / 269.6 degrees Elevation (low end): 79.0 ft Length: 12799.0 ft

windcomponents
(wind_dirs_deg, wind_speeds)¶ Resolves list of wind speeds and directions into runway/cross components on the current runway.
Parameters:
 wind_dirs_deg
List of floats. Wind directions expressed in degrees true (e.g., directions specified in a METAR).
 wind_speeds
List of floats. Wind_speeds (in the units in which the output is desired).
Outputs:
 runway_component
Scalar or numpy array. The runway direction component of the wind (sign convention: headwinds are positive).
 crosswind_component
Scalar or numpy array. The cross component of the wind (sign convention: winds from the right are positive).
Example
# Given a METAR, calculate the wind components on Rwy 09 at Yeovilton from ADRpy import atmospheres as at from metar import Metar runway = at.Runway('EGDY', 1) egdywx = Metar.Metar('EGDY 211350Z 30017G25KT 9999 FEW028 BKN038 08/01 Q1031') direction_deg = egdywx.wind_dir.value() windspeed_kts = egdywx.wind_speed.value() rwy_knots, cross_knots = runway.windcomponents(direction_deg, windspeed_kts) print("Runway component:", rwy_knots) print("Cross component:", cross_knots)
Output:
Runway component: 13.5946391943 Cross component: 10.2071438305

atmospheres.
geom2geop45m
(altitude_m)¶ Convert geometric height to geopotential (m) assuming 45deg lat

atmospheres.
geop2geom45m
(altitude_m)¶ Convert geometric height to geopotential (m) assuming 45deg lat

atmospheres.
idealgasdens_kgm3
(p_pa, temp_k)¶ Density from pressure and temperature, on ideal gas assumption

atmospheres.
idealgaspress_pa
(rho_kgpm3, temp_k)¶ Pressure from density and temperature, on ideal gas assumption

atmospheres.
mil_hdbk_310
(high_or_low, temp_or_dens, alt_km)¶ Load an atmospheric data set from US Military Handbook 310

atmospheres.
pistonpowerfactor
(density_kgpm3)¶ GaggFerrar model. Multiply by this to get power at given density.

atmospheres.
pressratio
(pressure_pa, mach)¶ Ratio of total pressure and the standard SL pressure

atmospheres.
reciprocalhdg
(heading_deg)¶ The reciprocal of a heading in degrees

atmospheres.
tatbysat
(mach, recfac=1.0)¶ Ratio of total and static air temperature at a given Mach no

atmospheres.
tempratio
(temp_c, mach)¶ Ratio of total temperature and the standard SL temperature

atmospheres.
turbofanthrustfactor
(temp_c, pressure_pa, mach, throttleratio=1, ptype='highbpr')¶ Multiply SL static thrust by this to get thrust at specified conditions

atmospheres.
turbojetthrustfactor
(temp_c, pressure_pa, mach, throttleratio=1, afterburner=False)¶ Multiply SL static thrust by this to get thrust at specified conditions

atmospheres.
turbopropthrustfactor
(temp_c, pressure_pa, mach, throttleratio=1)¶ Multiply SL static thrust by this to get thrust at specified conditions
Constraint Analysis Module¶
This module contains tools for the constraint analysis of fixed wing aircraft.

class
constraintanalysis.
AircraftConcept
(brief, design, performance, designatm)¶ Definition of a basic aircraft concept. This is the most important class in ADRpy. An object of this class defines an aircraft design in terms of the brief it is aiming to meet, high level design variables that specify it, key parameters that describe its performance, as well as the atmosphere it operates in. These are the four arguments that define an object of the AircraftConcept class. The first three are dictionaries, as described below, the last is an object of Atmosphere class.
Parameters:
 brief
Dictionary. Definition of the design brief, that is, the requirements the design seeks to meet. Contains the following key names:
 rwyelevation_m
Float. The elevation (in metres) of the runway againts which the takeoff constraint is defined. Optional, defaults to zero (sea level).
 groundrun_m
Float. Length (in metres) of takeoff ground run in meters at the elevation defined by the rwyelevation_m entry of the dictionary. This is a basic, 100% N1, no wind, zero runway gradient ground run.
 stloadfactor
Float. Load factor to be sustained by the aircraft in a steady, level turn.
 turnalt_m
Float. Altitude (in metres) where the turn requirement is defined. Optional, defaults to zero (sea level).
 turnspeed_ktas
Float. True airspeed (in knots) at which the turn requirement (above) has to be met. Since the dynamics of turning flight is dominated by inertia, which depends on ground speed, the turn speed is specified here as TAS (on the zero wind assumption). If you’d rather specify this as IAS/CAS/EAS, use eas2tas first to obtain the TAS value.
 climbalt_m
Float. The altitude (in metres) where the climb rate requirement is specified. Optional, defaults to zero (sea level).
 climbspeed_kias
Float. The airspeed (in knots, indicated) at which the required climb rate has to be achieved.
 climbrate_fpm
Float. Required climb rate (in feet per minute) at the altitude specified in the climbalt_m entry (above).
 cruisealt_m
Float. The altitude at which the cruise speed requirement will be defined.
 cruisespeed_ktas
Float. The required cruise speed (in knots, true airspeed) at the altitude specified in the cruisealt_m entry (above).
 cruisethrustfact
Float. The fraction (nondimensional) of the maximum available thrust at which the cruise speed requirement must be achieved.
 servceil_m
Float. The required service ceiling in meters (that is, the altitude at which the maximum rate of climb drops to 100 feet per minute).
 secclimbspd_kias
Float. The speed (knots indicated airspeed) at which the service ceiling must be reached. This should be an estimate of the best rate of climb speed.
 vstallclean_kcas
Float. The maximum acceptable stall speed (in knots, indicated/calibrated).
Example design brief:
brief = {'rwyelevation_m':0, 'groundrun_m':313, 'stloadfactor': 1.5, 'turnalt_m': 1000, 'turnspeed_ktas': 100, 'climbalt_m': 0, 'climbspeed_kias': 101, 'climbrate_fpm': 1398, 'cruisealt_m': 3048, 'cruisespeed_ktas': 182, 'cruisethrustfact': 1.0, 'servceil_m': 6580, 'secclimbspd_kias': 92, 'vstallclean_kcas': 69}
 design
Dictionary. Definition of key, high level design variables that define the future design.
 aspectratio
Float. Wing aspect ratio.
 sweep_le_deg
Float. Main wing leading edge sweep angle (in degrees). Optional, defaults to zero (no sweep).
 sweep_mt_deg
Float. Main wing sweep angle measured at the maximum thickness point. Optional, defaults to zero.
 bpr
Float. Specifies the propulsion system type. For jet engines (powered by axial gas turbines) this should be the bypass ratio (hence ‘bpr’). Set to 1 for piston engines, 2 for turboprops and 3 if no power/thrust corrections are needed (e.g., for electric motors).
 tr
Float. Throttle ratio for gas turbine engines. tr = 1 means that the Turbine Entry Temperature will reach its maximum allowable value in sea level standard day conditions, so higher ambient temperatures will result in power loss. Higher tr values mean thrust decay starting at higher altitudes.
 weightfractions
Dictionary, specifying at what fraction of the maximum takeoff weight do various constraints have to be met. It should contain the following keys: takeoff, climb, cruise, turn, servceil. Optional, each defaults to 1.0 if not specified.
 performance
Dictionary. Definition of key, high level design performance estimates.
 CDTO
Float. Takeoff drag coefficient.
 CLTO
Float. Takeoff lift coefficient.
 CLmaxTO
Float. Maximum lift coefficient in takeoff conditions.
 CLmaxclean
Float. Maximum lift coefficient in flight, in clean configuration.
 mu_R
Float. Coefficient of rolling resistance on the wheels.
 CDminclean
Float. Zero lift drag coefficient in clean configuration.
 etaprop
Dictionary. Propeller efficiency in various phases of the mission. It should contain the following keys: takeoff, climb, cruise, turn, servceil. Optional, unspecified entries in the dictionary default to the following values:
etap = {'takeoff': 0.45, 'climb': 0.75, 'cruise': 0.85, 'turn': 0.85, 'servceil': 0.65}
 designatm
Atmosphere class object. Specifies the virtual atmosphere in which all the design calculations within the AircraftConcept class will be performed.

bank2turnradius
(bankangle_deg)¶ Calculates the turn radius in m, given the turn TAS and the bank angle

bestclimbspeedprop
(wingloading_pa, altitude_m)¶ The best rate of climb speed for a propeller aircraft

induceddragfact
(whichoswald=1)¶ Lift induced drag factor k estimate (Cd = Cd0 + k.Cl^2)

map2static
()¶ Maps the average takeoff thrust to static thrust. If a bypass ratio is not specified, it returns a value of 1.

oswaldspaneff1
()¶ Raymer’s Oswald span efficiency estimate, sweep < 30, moderate AR

oswaldspaneff2
()¶ Oswald span efficiency estimate due to Brandt et al.

oswaldspaneff3
()¶ Raymer’s Oswald span efficiency estimate, swept wings

powerrequired
(wingloadinglist_pa, tow_kg, feasibleonly=True)¶ Calculate the power (in HP) required for t/o, trn, clm, crs, sec.

smincleanstall_m2
(weight_kg)¶ Minimum wing area defined by the clean stall CLmax and the weight

thrusttoweight_sustainedturn
(wingloading_pa)¶ Baseline T/W req’d for sustaining a given load factor at a certain altitude

thrusttoweight_takeoff
(wingloading_pa)¶ The thrust to weight ratio required for takeoff. This function is an implementation of the following simple, analytical model:
\[\frac{\overline{T}}{W} = 1.21\frac{W/S}{\rho C_\mathrm{Lmax}^\mathrm{TO}gd_ \mathrm{G}}+\frac{1}{2}\frac{C_\mathrm{D}^\mathrm{TO}}{C_\mathrm{L}^\mathrm{TO}} +\frac{1}{2}\mu_\mathrm{R}\]where \(\overline{T}\) is the average thrust during the takeoff run, \(W/S\) is the wing loading, \(d_\mathrm{G}\) is the required ground roll, \(C_\mathrm{D}^\mathrm{TO}\) and \(C_\mathrm{L}^\mathrm{TO}\) are the ‘all wheels on the runway’ drag and lift coefficient respectively in the takeoff configuration, \(C_\mathrm{Lmax}^\mathrm{TO}\) is the maximum lift coefficient achieved during the takeoff run (during rotation), \(\rho\) is the ambient density and \(\mu_\mathrm{R}\) is the coefficient of rolling resistance on the wheels.
This is a function exposed to the user for clarity and added flexibility. If you need to calculate the thrust to weight ratio required for takeoff, use
twrequired_to
. This corrects the output of this function to account for the environmental conditions (including their impact on engine performance) and includes a mapping to static thrust.thrusttoweight_takeoff
should only be used if you would like to perform these corrections in a different way than implemented intwrequired_to
.If a full constraint analysis is required,
twrequired
should be used. A similar ‘full constraint set’ function is available for calculating the power demanded of the engine of a propellerdriven engine or electric motor (to satisfy the constraint set)  this is calledpowerrequired
.

twrequired
(wingloadinglist_pa, feasibleonly=True)¶ Calculate the T/W required for t/o, trn, clm, crs, sec.
This method integrates the full set of constraints and it gives the user a compact way of performing a full constraint analysis. If a specific constraint is required only, the individual methods can be called separately:
twrequired_to
(takeoff),twrequired_trn
(turn),twrequired_clm
(climb),twrequired_trn
(turn),twrequired_crs
(cruise),twrequired_sec
(service ceiling).Parameters
 wingloading_pa
float or numpy array, list of wing loading values in Pa.
Returns
 twreq
dictionary variable, wherein each entry contains vectors related to one of the constraints:
twreq['takeoff']
(T/W required for takeoff),twreq['liftoffspeed_mps']
(liftoff speed in m/s),twreq['avspeed_mps']
(average speed of the takeoff run, in m/s),twreq['turn']
(T/W required for the turn),twreq['turnfeasible']
(same astwreq['turn']
, but with NaN where the maximum lift coefficient is exceeded),twreq['turncl']
(lift coefficient required in the turn),twreq['climb']
(T/W required for climb),twreq['cruise']
(T/W required for cruise),twreq['servceil']
(T/W required for the service ceiling constraint),twreq['combined']
(the T/W required to meet all of the above).

twrequired_clm
(wingloading_pa)¶ Calculates the T/W required for climbing for a range of wing loadings.
Parameters
 wingloading_pa
float or numpy array, list of wing loading values in Pa.
Returns
 twratio
array, thrust to weight ratio required for the given wing loadings.
See also
twrequired
Notes
1. Use twrequired if a full constraint analysis is desired, as this integrates the takeoff, turn, climb, cruise, and service ceiling constraints, as well as computing the combined constraint boundary.
2. The calculation currently approximates climb performance on the constant TAS assumption (though note that the design brief dictionary variable must specify the climb speed as IAS, which is the operationally relevant figure)  a future version of the code will remove this approximation and assume constant IAS.
Example
Given a climb rate (in feet per minute) and a climb speed (KIAS), as well as an altitude (in a given atmosphere) where these must be achieved, as well as a set of basic geometrical and aerodynamic performance parameters, compute the necessary T/W ratio to hold the specified climb rate.
from ADRpy import atmospheres as at from ADRpy import constraintanalysis as ca designbrief = {'climbalt_m': 0, 'climbspeed_kias': 101, 'climbrate_fpm': 1398} etap = {'climb': 0.8} designperformance = {'CDminclean': 0.0254, 'etaprop' :etap} designdef = {'aspectratio': 10.12, 'sweep_le_deg': 2, 'sweep_mt_deg': 0, 'bpr': 1} TOW_kg = 1542.0 designatm = at.Atmosphere() concept = ca.AircraftConcept(designbrief, designdef, designperformance, designatm) wingloadinglist_pa = [1250, 1500, 1750] twratio = concept.twrequired_clm(wingloadinglist_pa) print('T/W: ', twratio)
Output:
T/W: [ 0.20249491 0.2033384 0.20578177]

twrequired_crs
(wingloading_pa)¶ Calculate the T/W required for cruise for a range of wing loadings

twrequired_sec
(wingloading_pa)¶ T/W required for a service ceiling for a range of wing loadings

twrequired_to
(wingloading_pa)¶ Calculate the T/W required for takeoff for a range of wing loadings
Parameters
 wingloading_pa
float or numpy array, list of wing loading values in Pa.
Returns
 twratio
array, thrust to weight ratio required for the given wing loadings.
 liftoffspeed_mpstas
array, liftoff speeds (TAS  true airspeed) in m/s.
 avspeed_mps
average speed (TAS) during the takeoff run, in m/s.
See also
twrequired
Notes
1. The calculations here assume a ‘no wind’ takeoff, conflating ground speed (GS) and true airspeed (TAS).
2. Use twrequired if a full constraint analysis is desired, as this integrates the takeoff, turn, climb, cruise, and service ceiling constraints, as well as computing the combined constraint boundary.
Example
from ADRpy import atmospheres as at from ADRpy import constraintanalysis as ca designbrief = {'rwyelevation_m':1000, 'groundrun_m':1200} designdefinition = {'aspectratio':7.3, 'bpr':3.9, 'tr':1.05} designperformance = {'CDTO':0.04, 'CLTO':0.9, 'CLmaxTO':1.6, 'mu_R':0.02} wingloadinglist_pa = [2000, 3000, 4000, 5000] atm = at.Atmosphere() concept = ca.AircraftConcept(designbrief, designdefinition, designperformance, atm) tw_sl, liftoffspeed_mpstas, _ = concept.twrequired_to(wingloadinglist_pa) print(tw_sl) print(liftoffspeed_mpstas)
Output:
[ 0.19397876 0.26758006 0.33994772 0.41110154] [ 52.16511207 63.88895348 73.77260898 82.48028428]

twrequired_trn
(wingloading_pa)¶ Calculates the T/W required for turning for a range of wing loadings
Parameters
 wingloading_pa
float or numpy array, list of wing loading values in Pa.
Returns
 twratio
array, thrust to weight ratio required for the given wing loadings.
 clrequired
array, lift coefficient values required for the turn (see notes).
 feasibletw
as twratio, but contains NaNs in lieu of unachievable (CLmax exceeded) values.
See also
twrequired
Notes
1. Use twrequired if a full constraint analysis is desired, as this integrates the takeoff, turn, climb, cruise, and service ceiling constraints, as well as computing the combined constraint boundary.
2. At the higher end of the wing loading range (low wing area values) the CL required to achieve the required turn rate may exceed the maximum clean CL (as specified in the CLmaxclean entry in the performance dictionary argument of the AircraftConcept class object being used). This means that, whatever the T/W ratio, the wings will stall at this point. The basic T/W value will still be returned in twratio, but there is another output, feasibletw, which is an array of the same T/W values, with those values blanked out (replaced with NaN) that cannot be achieved due to CL exceeding the maximum clean lift coefficient.
Example
Given a load factor, an altitude (in a given atmosphere) and a true airspeed, as well as a set of basic geometrical and aerodynamic performance parameters, compute the necessary T/W ratio to hold that load factor in the turn.
from ADRpy import atmospheres as at from ADRpy import constraintanalysis as ca from ADRpy import unitconversions as co designbrief = {'stloadfactor': 2, 'turnalt_m': co.feet2m(10000), 'turnspeed_ktas': 140} etap = {'turn': 0.85} designperformance = {'CLmaxclean': 1.45, 'CDminclean':0.02541, 'etaprop': etap} designdef = {'aspectratio': 10.12, 'sweep_le_deg': 2, 'sweep_mt_deg': 0, 'bpr': 1} designatm = at.Atmosphere() concept = ca.AircraftConcept(designbrief, designdef, designperformance, designatm) wingloadinglist_pa = [1250, 1500, 1750] twratio, clrequired, feasibletw = concept.twrequired_trn(wingloadinglist_pa) print('T/W: ', twratio) print('Only feasible T/Ws:', feasibletw) print('CL required: ', clrequired) print('CLmax clean: ', designperformance['CLmaxclean'])
Output:
T/W: [ 0.19920641 0.21420513 0.23243016] Only feasible T/Ws: [ 0.19920641 0.21420513 nan] CL required: [ 1.06552292 1.2786275 1.49173209] CLmax clean: 1.45

vstall_kias
(wingloadinglist_pa, clmax)¶ Calculates the stall speed (indicated) for a given wing loading in a specified cofiguration.
Parameters:
 wingloading_pa
float or numpy array, list of wing loading values in Pa.
 clmax
maximum lift coefficient (float) or the name of a standard configuration (string) for which a maximum lift coefficient was specified in the
performance
dictionary (currently implemented: ‘takeoff’).
Returns:
stall speed in knots (float or numpy array)
Note:
The calculation is performed assuming standard day ISA sea level conditions (not in the conditions specified in the atmosphere used when instantiating the
AircraftConcept
object!) so the speed returned is an indicated (IAS) / calibrated (CAS) value.Example:
from ADRpy import constraintanalysis as ca designperformance = {'CLmaxTO':1.6} concept = ca.AircraftConcept({}, {}, designperformance, {}) wingloading_pa = 3500 print("VS1(takeoff):", concept.vstall_kias(wingloading_pa, 'takeoff'))

wigfactor
()¶ Wingingroundeffect factor to account for the change in induced drag as a result of the wing being in close proximity of the ground. Specify the entry wingheightratio in the design dictionary variable you instantiated the AircraftConcept object with in order to compute this  if unspecified, a call to this method will result in a value practically equal to 1 being returned.
The factor, following McCormick (“Aerodynamics, Aeronautics, and Flight Mechanics”, Wiley, 1979) and Gudmundsson (2013) is calculated as:
\[\Phi = \frac{(16\,h/b)^2}{1+(16\,h/b)^2}\]where \(h/b\) is design[‘wingheightratio’]: the ratio of the height of the wing above the ground (when the aircraft is on the runway) and the span of the main wing.
The induced drag coefficient adjusted for ground effect thus becomes:
\[C_\mathrm{Di} = \Phi C_\mathrm{Di}^\mathrm{oge},\]where the ‘oge’ superscript denotes the ‘out of ground effect’ value.
Example:
import math from ADRpy import constraintanalysis as co designdef = {'aspectratio':8} wingarea_m2 = 10 wingspan_m = math.sqrt(designdef['aspectratio'] * wingarea_m2) for wingheight_m in [0.6, 0.8, 1.0]: designdef['wingheightratio'] = wingheight_m / wingspan_m aircraft = co.AircraftConcept({}, designdef, {}, {}) print('h/b: ', designdef['wingheightratio'], ' Phi: ', aircraft.wigfactor())
Output:
h/b: 0.06708203932499368 Phi: 0.5353159851301115 h/b: 0.08944271909999159 Phi: 0.6719160104986877 h/b: 0.11180339887498948 Phi: 0.761904761904762

wsmaxcleanstall_pa
()¶ Maximum wing loading defined by the clean stall Clmax

constraintanalysis.
tw2pw
(thrusttoweight, speed, etap)¶ Converts thrust to weight to power to weight (propellerdriven aircraft)
Parameters
 thrusttoweight
thrust to weight ratio (nondimensional)
 speed
ground speed (in m/s if output in Watts / Newton is required)
 etap
propeller efficiency (nondimensional), float
Returns
power to weight ratio (in W/N if speed is in m/s)
See also
powerrequired
Notes
1. A note on units. If the input speed is in m/s, the other two inputs being nondimensional, the output product is also in m/s, which is equal to W/N (W / N = (J/s) / N = (Nm/s) / N = m/s).
2. The speed input is a kinematic quantity, not an airspeed, so it is generally a ground speed (GS) or a true airspeed (TAS) if we are assuming zero wind.
3. The inputs to the function are scalars or a mix of scalars and numpy arrays.
Example:
from ADRpy import constraintanalysis as ca from ADRpy import atmospheres as at from ADRpy import unitconversions as co designbrief = {'stloadfactor': 2, 'turnalt_m': 3050, 'turnspeed_ktas': 140} etap = {'turn': 0.85} designperformance = {'CLmaxclean': 1.45, 'CDminclean': 0.02541, 'etaprop': etap} designdef = {'aspectratio': 10, 'sweep_le_deg': 2, 'sweep_mt_deg': 0, 'bpr': 1} TOW_kg = 1500 designatm = at.Atmosphere() concept = ca.AircraftConcept(designbrief, designdef, designperformance, designatm) wingloading_pa = 1000 twreq, _, _ = concept.twrequired_trn(wingloading_pa) turnspeed_mpstas = co.kts2mps(designbrief['turnspeed_ktas']) pw_trn_wpn = ca.tw2pw(twreq, turnspeed_mpstas, etap['turn']) pw_trn_hpkg = co.wn2hpkg(pw_trn_wpn) p_trn_hp = pw_trn_hpkg * TOW_kg print(p_trn_hp)
Output:
318.691213406
Unit Conversions¶
This module contains tools for converting between units commonly used in aircraft design.

unitconversions.
c2f
(temp_c)¶ Convert temperature value from Celsius to Fahrenheit

unitconversions.
c2k
(temp_c)¶ Convert temperature value from Celsius to Kelvin

unitconversions.
c2r
(temp_c)¶ Convert temperature value from Celsius to Rankine

unitconversions.
feet22m2
(area_ft2)¶ Converts area value from feet squared to meters squared

unitconversions.
feet2m
(length_feet)¶ Converts length value from feet to meters

unitconversions.
fpm2mps
(speed_fpm)¶ Convert speed value from feet/min to m/s

unitconversions.
hp2kw
(power_hp)¶ Convert power from HP to kW

unitconversions.
inhg2mbar
(press_inhg)¶ Convert pressure value from inHg to mbar

unitconversions.
k2c
(temp_k)¶ Convert temperature value from Kelvin to Celsius

unitconversions.
k2r
(temp_k)¶ Convert temperature value from Kelvin to Rankine

unitconversions.
kg2lbs
(mass_kg)¶ Convert mass value from kg to lbs

unitconversions.
kg2n
(mass_kg)¶ Converts mass in kg to weight in N

unitconversions.
kgm22pa
(pressure_kgm2)¶ Convert pressure value from kg/m^2 to Pa

unitconversions.
kgm32sft3
(density_kgm3)¶ Convert density from kg/m^3 to slugs/ft^3

unitconversions.
km2m
(length_km)¶ Converts length value from kilometres to metres

unitconversions.
kts2mps
(speed_kts)¶ Convert speed value knots to mps

unitconversions.
kw2hp
(power_kw)¶ Convert power from kW to HP

unitconversions.
lbf2n
(force_lbf)¶ Convert force from lbf to N

unitconversions.
lbfft22mbar
(press_lbfft2)¶ Convert pressure value from lb/ft^2 to mbar

unitconversions.
lbs2kg
(mass_lbs)¶ Convert mass value from lbs to kg

unitconversions.
m22feet2
(area_m2)¶ Converts area value from meters squared to feet squared

unitconversions.
m2feet
(length_m)¶ Convert length value from meters to feet

unitconversions.
m2km
(length_m)¶ Converts length value from meters to kilometres

unitconversions.
mbar2inhg
(press_mbar)¶ Convert pressure value from mbar to inHg

unitconversions.
mbar2lbfft2
(press_mbar)¶ Convert pressure value from mbar to lb/ft^2

unitconversions.
mbar2pa
(press_mbar)¶ Convert pressure value from mbar to Pascal

unitconversions.
mps2kts
(speed_mps)¶ Convert speed value from m/s to knots

unitconversions.
n2kg
(force_n)¶ Converts force in N to mass in kg

unitconversions.
n2lbf
(force_n)¶ Convert force from N to lbf

unitconversions.
pa2kgm2
(pressure_pa)¶ Convert pressure value from Pa to kg/m^2

unitconversions.
pa2mbar
(press_pa)¶ Convert pressure value from Pascal to mbar

unitconversions.
r2c
(temp_r)¶ Convert temperature value from Rankine to Celsius

unitconversions.
r2k
(temp_r)¶ Convert temperature value from Rankine to Kelvin

unitconversions.
sft32kgm3
(density_slft3)¶ Convert density from slugs/ft^3 to kg/m^3

unitconversions.
wn2hpkg
(powertoweight_wn)¶ Convert power to weight (Watt/N) to hp/kg

unitconversions.
wn2kwkg
(powertoweight_wn)¶ Convert power to weight (Watt/N) to kW/kg

unitconversions.
wn2wkg
(powertoweight_wn)¶ Convert power to weight (Watt/N) to W/kg
Miscellaneous Utilities¶
This module contains miscellaneous tools to support aircraft engineering calculations.
Multipanel plots with a shared yaxis, e.g., for atmosphere profiles. See the Jupyter notebook Introduction_to_Modelling_the_Atmosphere… in the docs/ADRpy directory for usage examples.

mtools4acdc.
polyblend
(time, time_f, signal_i, signal_f)¶ A smooth blend between two levels of a signal. Suitable for approximating thrust variations associated with spoolup and spooldown, etc.

mtools4acdc.
recastasnpfloatarray
(scalarorvec)¶ Recasts an arbitrary argument as a numpy float array. Used internally by some of the constraint calculations to increase robustness, though the use of numpy arrays as inputs is the recommended approach in most cases.