{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Example Usage - `py_atmosphere`\n", "\n", "This document displays how to use `py_atmosphere` to extract atmospheric properties from the package, transform units and calculate Mach number for an object moving through stagnant air:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Import Package Functions" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from py_atmosphere.py_atmosphere import py_atmosphere\n", "from py_atmosphere.mach_number import mach_number\n", "from py_atmosphere.temp_conversion import temp_conversion" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Technical Background" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This package contains the mathematical representation of NASA's Glenn Research Center [Earth Atmosphere Model](https://www.grc.nasa.gov/www/k-12/airplane/atmosmet.html#:~:text=In%20the%20troposphere%2C%20the%20temperature,atmosphere%20model%20is%20also%20available), which is a simplified representation of the International Standard Atmosphere.\n", "\n", "Under this context, the Earth's atmosphere is considered a sheet of air extending from the Earth's surface to the edge of space. Within the atmosphere, very complex chemical, thermodynamic and fluid dynamics effects occur. Given these effects, the properties of the air are constantly changing with time and place.\n", "\n", "These effects have the following instintive impacts:\n", "- Given the effect that the sun has on the surface of the Earth, and how this heat is diffused up through the atmosphere, the air temperature is highest near the surface of the planet and decreases with increasing altitude.\n", "- The pressure of the air is related to the weight of the air over a given location. As we increase altitude through the atmosphere, the amount of air above us is less. For this reason, air pressure decreases as altitude increases.\n", "\n", "These notions are incredibly important in the Aerospace industry, as how the atmosphere and the air properties change can have a direct impact in Aircraft operation throughout the flight envelope of an aircraft, for example. To help aircraft designers, it is useful to have a Standard Atmosphere model of the variation of properties throughout the atmosphere. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The `py_atmosphere()` function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we need to give a brief introduction to the modeled layers of the atmosphere.\n", "\n", "- From 0 to 11,000 meters, we have the Troposphere.\n", "- From 11,000 meters to 25,000 meters, we have the Lower Stratosphere.\n", "- Beyond 25,000 meters, we have the Upper Stratosphere\n", "\n", "Note: This implementation of the model is restricted to an input altitude of 0m to 25,000 m. Higher altitudes require more complex modeling to avoid significant inaccuracies, which are out of the scope of this package. The selected range is sufficient when considering that the average altitude during cruise flight in civil aircraft is between 10,000 and 12,000 meters. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The standard model consists of the following equations to calculate Temperature and Pressure given an Altitude.\n", "\n", "Variables:\n", "\n", "- T = Temperature (°C - degrees Celsius)\n", "- P = Pressure (K-Pa - KiloPascal)\n", "- h = Altitude (m - meters)\n", "\n", "In the Troposphere, for:\n", "```{math}\n", "```\n", "$$h < 11,000m$$\n", "$$T = 15.04 - 0.00649*h$$\n", "$$P = 101.29 * [{\\frac{T + 273.1}{288.08}}]^{5.256}$$\n", "\n", "In the Lower Stratosphere, for:\n", "$$11,000m < h < 25,000m$$\n", "$$T = -56.46$$\n", "$$P = 22.65 * e^{1.73-0.000157*h}$$\n", "\n", "For the Upper Stratosphere, for:\n", "$$h > 25,000m$$\n", "$$T = -131.21 + 0.00299*h$$\n", "$$P = 2.488 * [{\\frac{T + 273.1}{216.6}}]^{-11.388}$$\n", "\n", "Considering these equations, we can use the `py_atmosphere` function to calculate the standard pressure and temperature given an altitude. Depending on the inquired altitude, the package will select the appropriate set of equations to calculate Temperature and Pressure.\n", "\n", "Note that the inquired altitude may be entered in different units:\n", "\n", "- `m` for meters\n", "- `km` for kilometers\n", "- `feet` for feet\n", "- `miles` for miles\n", "\n", "Example: Calculate the Pressure and Temperature at an altitude of 0 meters, 10 kilometers, 10,000 ft and 15 miles:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 101.29]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "py_atmosphere(0, \"m\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to read the output: At an altitude of 0 meters, the standard atmosphere calculates an air Temperature of 15°C and air Pressure of 101.29 kiloPascals." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[10000, -49.86000000000001, 26.547435615976987]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "py_atmosphere(10, \"km\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to read the output: At an altitude of 10 kilometers, the standard atmosphere calculates an air Temperature of -49.86°C and air Pressure of 26.54 kiloPascals. Note that the output converts entered altitude to meters. In this case, 1 kilometer is equal to 10,000 meters." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3048.0, -4.741520000000001, 69.84232244791907]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "py_atmosphere(10000, \"ft\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to read the output: At an altitude of 10,000 feet, the standard atmosphere calculates an air Temperature of -4.74°C and air Pressure of 69.84 kiloPascals. Note that the output converts entered altitude to meters. In this case, 10,000 feet is equal to 3,048 meters." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[24140.1, -56.46, 2.886844831523778]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "py_atmosphere(15, \"miles\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to read the output: At an altitude of 15 miles, the standard atmosphere calculates an air Temperature of -56.46°C and air Pressure of 2.88 kiloPascals. Note that the output converts entered altitude to meters. In this case, 15 miles is equal to 24,140 meters." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As mentioned, the function does not work for altitude outside of the range of 0 to 25,000 meters." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Expected error: Altitude must be a non-negative value. Altitude must be a non-negative value\n" ] } ], "source": [ "try:\n", " py_atmosphere(-1, \"m\")\n", "except ValueError as e:\n", " print(f\"Expected error: {e}. Altitude must be a non-negative value\")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Expected error: Invalid altitude value. Model maximum value is 25,000 m.. Invalid altitude value. Model maximum value is 25,000 m.\n" ] } ], "source": [ "try:\n", " py_atmosphere(25001, \"m\")\n", "except ValueError as e:\n", " print(f\"Expected error: {e}. Invalid altitude value. Model maximum value is 25,000 m.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The `temp_conversion()` function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Given the frequent need to see these properties in different units, the `py_atmosphere` package contains a function to perform convenient conversions for altitude, temperature and pressure. The input and output of this function shares the same list structure as the output from the `py_atmosphere` function.\n", "\n", "This function requires the user to select which property needs conversion and to which units. Note that the package can currently perform only one conversion at a time.\n", "\n", "The conversion units accepted for each property are:\n", "\n", "- Altitude: \"m\" for meters, \"km\" for kilometers, \"ft\" for feet, and \"miles\" for miles.\n", "- Temperature: \"C\" for Celsius, \"F\" for Fahrenheit, \"K\" for Kelvin, and \"R\" for Rankine.\n", "- Pressure: \"kPa\" for KiloPascal, \"bar\" for Pascal, and \"psia\" for pounds per square inch. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Temperature Conversions" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 101.29]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example_temperature = py_atmosphere(0, \"m\")\n", "example_temperature" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 101.29]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_temperature, \"temperature\", \"C\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 59.071999999999996, 101.29]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_temperature, \"temperature\", \"F\")" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 288.19, 101.29]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_temperature, \"temperature\", \"K\")" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 518.742, 101.29]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_temperature, \"temperature\", \"R\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pressure Conversions" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 101.29]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example_pressure = py_atmosphere(0, \"m\")\n", "example_pressure" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 101.29]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_pressure, \"pressure\", \"kPa\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 1.0129000000000001]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_pressure, \"pressure\", \"bar\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 15.04, 14.690868633000001]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_pressure, \"pressure\", \"psia\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Altitude Conversion" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1000, 8.549999999999999, 90.04204320972651]" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "example_altitude = py_atmosphere(1000, \"m\")\n", "example_altitude" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1000, 8.549999999999999, 90.04204320972651]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_altitude, \"altitude\", \"m\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1.0, 8.549999999999999, 90.04204320972651]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_altitude, \"altitude\", \"km\")" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3280.84, 8.549999999999999, 90.04204320972651]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_altitude, \"altitude\", \"ft\")" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0.621371, 8.549999999999999, 90.04204320972651]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_conversion(example_altitude, \"altitude\", \"miles\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The `mach_number()` function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `py_atmosphere` package is also prepared to calculate the Mach Number of a moving object in stagnant air.\n", "\n", "Taking a step back, it is necessary to describe the concept of [Speed of Sound](https://www.grc.nasa.gov/www/BGH/sound.html). Speed of sound (`a`) is the speed in which sound (or formally, a sound wave) propagates though a medium. In an ideal gas (a common assumption in design activities that describes how gases beave), the speed of sound is only dependent on the medium's temperature and composition.\n", "\n", "$$a = \\sqrt{\\gamma RT}$$\n", "\n", "Where:\n", "\n", "- Air property `gamma` - Ratio of specific heats - 1.4 for air.\n", "- Air property `R` - Gas constant - 287.05 J / kg * K\n", "- `T` - Air temperature in K\n", "\n", "The Mach Number is dimensionless quantity in fluid dynamics that represents the ratio of flow velocity around a boundary relative to the local speed of sound. In aerospace applications, this ratio represents the relation between an aircraft's speed as it moves through stagnant air, where the local speed of sound is a property that is only function of the local temperature.\n", "\n", "The Mach number is widely used throughout fluid mechanics applications as it is descriptive of the compressibility of the fluids. In the Aerospace industry it is also descriptive of subsonic, sonic and supersonic flight. Therefore, it is an invaluable design parameter.\n", "\n", "$$Ma = \\frac{c}{a}$$\n", "\n", "Where:\n", "\n", "- `a` - Speed of Sound in medium\n", "- `c` - Speed of an object through same medium\n", "\n", "The `mach_number` function takes the temperature calculated by the `py_atmosphere` function, and along with an input `speed` of an object, it calculates the Mach Number. Given that temperature is a function of altitude, we can see that for an object moving at a constant speed, the Mach number changes with altitude, as temperature changes as well. \n", "\n", "Under this consideration, the `mach_number` function receives an `altitude`, altitude `units` and object `speed` in meters per second. Note that just as the `py_atmosphere` function, `mach_number` also accepts altitude units in \"m\" for meters, \"km\" for kilometers, \"ft\" for feet, and \"miles\" for miles." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Example: \n", "\n", "What is the Mach Number of an object moving at 350 m/s?\n", "\n", "Note: A Mach Number < 1 describes \"subsonic\" flight, a Mach Number = 1 describes \"sonic\" flight, and Mach Number > 1 describes \"supersonic\" flight.\n", "\n", "First, at an altitude of 0 meters:\n", "\n", "We can see that an object moving at 300 m/s at an altitude of 0 meters describes a \"Subsonic\" movement." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.8815338791328668" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mach_number(0, \"m\", 300)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that an object moving at the same 300 m/s, but at an altitude of 10,000 meters, describes supersonic flight (in other words, it is breaking the sound barrier!)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.0014835599066014" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mach_number(10000, \"m\", 300)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.11" } }, "nbformat": 4, "nbformat_minor": 4 }