balloon-calc/notebooks/hotair-box.ipynb

346 wiersze
12 KiB
Plaintext
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"id": "33295fc3-e98b-4c17-bca0-366c3a80c9c8",
"metadata": {
"extensions": {
"jupyter_dashboards": {
"activeView": "grid_default",
"views": {
"grid_default": {
"col": 0,
"height": 1,
"hidden": false,
"row": 0,
"width": 1
}
}
}
},
"tags": []
},
"source": [
"## Hot air balloon - lift calculator\n",
"### Box shape\n",
"[Source code](https://gitea.citizen4.eu/sp9unb/balloon-calc) \n",
"\n",
"[Run in mybinder.org IDE](https://mybinder.org/v2/git/https%3A%2F%2Fgitea.citizen4.eu%2Fsp9unb%2Fballoon-calc/HEAD?labpath=work%2Fhotair-box.ipynb) "
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "6ea87a15-f571-4611-8487-5b7556e2ef45",
"metadata": {
"extensions": {
"jupyter_dashboards": {
"activeView": "grid_default",
"views": {
"grid_default": {
"col": null,
"height": 2,
"hidden": true,
"row": null,
"width": 2
}
}
}
}
},
"outputs": [],
"source": [
"# https://pythreejs.readthedocs.io\n",
"from pythreejs import *\n",
"from IPython.display import HTML,display\n",
"from math import pi\n",
"\n",
"# https://ipywidgets.readthedocs.io\n",
"import ipywidgets as widgets\n",
"from ipywidgets import Layout\n",
"\n",
"# https://pypi.org/project/termcolor/\n",
"from termcolor import colored\n",
"\n",
"#from scipy.interpolate import interp1d\n",
"#import numpy as np\n",
"\n",
"#math\n",
"from math import sin, tan, sqrt"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "d075a994-76bb-46f7-bdfb-cc6ef449dc43",
"metadata": {
"extensions": {
"jupyter_dashboards": {
"activeView": "grid_default",
"views": {
"grid_default": {
"col": null,
"height": 2,
"hidden": true,
"row": null,
"width": 2
}
}
}
}
},
"outputs": [],
"source": [
"# air density–temperature relationship at 1 atm or 101.325 kPa\n",
"# https://en.wikipedia.org/wiki/Density_of_air\n",
"# https://www.engineersedge.com/calculators/air-density.htm\n",
"# temp in st.C density in g/m3\n",
"\n",
"#temp = [-25,-20,-15,-10,-5,0,5,10,15,20,25,30,35]\n",
"#dens = [1422.4,1394.3,1367.3,1341.3,1316.3,1292.2,1269.0,1246.6,1225.0,1204.1,1183.9,1164.4,1145.5]\n",
"#dens_temp_func = interp1d(temp, dens)\n",
"\n",
"\n",
"def airDensity(temp=0.0):\n",
" tempK = temp + 273.0 # absolute temperature [K]\n",
" p = 101325.0 # pressure [Pa]\n",
" rSpec = 287.0500676 # specific gas constant for dry air [J⋅kg1⋅K1]\n",
" return 1000.0 * p / ( rSpec * tempK )"
]
},
{
"cell_type": "code",
"execution_count": 40,
"id": "0e94979b-5973-4607-9d5f-e7b597a8374f",
"metadata": {},
"outputs": [],
"source": [
"# Ascent rate at ground level\n",
"# https://northstar-www.dartmouth.edu/~klynch/pmwiki-gc/uploads/BalloonCalulations.pdf\n",
"\n",
"# Coefficient of Drag assumed to 0.3 (flat top)\n",
"Cd = 0.3\n",
"g = 9.81 # [m/s2]\n",
"\n",
"def ascentRate(volume=1.0, airDens=1.0, liftForce=1.0, topArea=1.0): \n",
" val = ( 2 * liftForce * g ) / ( Cd * airDens * topArea )\n",
" if val < 0.0:\n",
" val = 0.0\n",
" return sqrt( val )\n"
]
},
{
"cell_type": "code",
"execution_count": 41,
"id": "2f3b63fd-d5ea-40b6-a2f9-b31c84cfef36",
"metadata": {
"extensions": {
"jupyter_dashboards": {
"activeView": "grid_default",
"views": {
"grid_default": {
"col": null,
"height": 2,
"hidden": true,
"row": null,
"width": 2
}
}
}
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7cd59b71891c4d47b1ab8c9e559e5cfd",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(FloatSlider(value=2.0, description='Width [m]:', layout=Layout(width='500px'), max=5.0, min=0.1…"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def f(width,height,depth,airTemp,hotAirTemp,coatDens,tapeDens,payloadWeight):\n",
" \n",
" \n",
" out=widgets.Output(layout={'margin': '10px 10px 10px 20px'}) \n",
" with out: \n",
" # Volume\n",
" volume = width * height * depth\n",
" print( \"{:<20}{:>6.1f} [m3]\".format(\"Volume:\",volume)) \n",
" # Area\n",
" area = 2 * (width * height + width * depth + height * depth)\n",
" print( \"{:<20}{:>6.1f} [m2]\".format(\"Area:\",area)) \n",
" # Coating density (protective film for painting): 300g / 4x5m = 15g/m2 \n",
" coatingWeight = coatDens * area\n",
" print( \"{:<20}{:>6.1f} [g]\".format(\"Coating weight:\",coatingWeight)) \n",
" # adhesive tape density : average 2g/m \n",
" tapeLength = 2 * width + 2 * depth + 4 * height\n",
" tapeWeight = tapeDens * tapeLength\n",
" print( \"{:<20}{:>6.1f} [m]\".format(\"Adh.tape length:\",tapeLength)) \n",
" print( \"{:<20}{:>6.1f} [g]\".format(\"Adh.tape weight:\",tapeWeight)) \n",
" totalWeight = coatingWeight + tapeWeight\n",
" print( \"{:<20}{:>6.1f} [g]\".format(\"Total ball. weight:\",totalWeight))\n",
" # Lift per volume g/m3 \n",
" # airDens = dens_temp_func( airTemp )\n",
" # hotAirDens = dens_temp_func( hotAirTemp ) \n",
" airDens = airDensity( airTemp )\n",
" hotAirDens = airDensity( hotAirTemp ) \n",
" lift = airDens - hotAirDens\n",
" print( \"{:<20}{:>6.1f} [g/m3]\".format(\"Lift/volume:\",lift)) \n",
" # Total lift force lift * volume \n",
" totalLiftForce = lift * volume\n",
" print( \"{:<20}{:>6.1f} [g]\".format(\"Total lift force:\",totalLiftForce)) \n",
" # Free lift force totalLiftForce - coatingWeight \n",
" freeLiftForce = totalLiftForce - totalWeight - payloadWeight\n",
" if freeLiftForce < 0:\n",
" color = 'red'\n",
" else:\n",
" color = None\n",
" print( colored(\"{:<20}{:>6.1f} [g]\".format(\"Free lift force:\",freeLiftForce),color)) \n",
" # Ascent rate \n",
" topArea = width * depth\n",
" ascRate = ascentRate(volume, airDens/1000.0, freeLiftForce/1000.0, topArea)\n",
" print( \"{:<20}{:>6.1f} [m/s]\".format(\"Ascent rate:\",ascRate)) \n",
"\n",
" geometry=BoxBufferGeometry(\n",
" width=width, \n",
" height=height, \n",
" depth=depth,\n",
" widthSegments=5, \n",
" heightSegments=10,\n",
" depthSegments=15)\n",
"\n",
" box = Mesh(geometry=geometry,\n",
" material=MeshLambertMaterial(color='gray')\n",
" )\n",
" \n",
"\n",
"# [ width, height, depth ]\n",
" w2 = width/2\n",
" h2 = height/2\n",
" d2 = depth/2\n",
" w2n = -1 * width/2\n",
" h2n = -1 * height/2\n",
" d2n = -1 * depth/2\n",
" tapeGeometry = LineSegmentsGeometry(\n",
" positions=[\n",
" [[w2, h2, d2], [w2, h2n, d2]],\n",
" [[w2, h2, d2], [w2n, h2, d2]],\n",
" [[w2n, h2, d2], [w2n, h2n, d2]], \n",
" [[w2, h2, d2n], [w2, h2n, d2n]],\n",
" [[w2, h2, d2n], [w2n, h2, d2n]],\n",
" [[w2n, h2,d2n], [w2n, h2n, d2n]], \n",
" [[w2, h2n,d2], [w2, h2n, d2n]],\n",
" [[w2n, h2n,d2], [w2n, h2n, d2n]] \n",
" ],\n",
" ) \n",
" tapeMaterial = LineMaterial(linewidth=3, color='#ffffff') \n",
" tape = LineSegments2( tapeGeometry, tapeMaterial ) \n",
" \n",
" \n",
" keyLight = DirectionalLight(color='white', position=[3, 5, 1], intensity=0.5)\n",
"\n",
" c = PerspectiveCamera(position=[2, 2, 5], up=[0, 1, 0], children=[keyLight])\n",
"\n",
" scene = Scene(children=[box, tape, c, AmbientLight(color='#777777')], background=None)\n",
"\n",
" renderer = Renderer(camera=c,\n",
" scene=scene,\n",
" alpha=True,\n",
" clearOpacity=1.0,\n",
" clearColor='#62a0ea',\n",
" controls=[OrbitControls(controlling=c)]\n",
" )\n",
" \n",
" display(widgets.HBox([renderer, out])) \n",
"# return renderer\n",
"\n",
"\n",
" display(HTML('''<style>\n",
" .widget-hbox { margin-top: 20px; }\n",
" </style>'''))\n",
"\n",
"layout=Layout(width='500px')\n",
"style = {'description_width': 'initial'}\n",
" \n",
"width=widgets.FloatSlider(min=0.1, max=5.0, step=0.1, value=2.0, description='Width [m]:',readout_format='.1f',layout=layout,style=style) \n",
"height=widgets.FloatSlider(min=0.1, max=5.0, step=0.1, value=2.0, description='Height [m]:',readout_format='.1f',layout=layout,style=style) \n",
"depth=widgets.FloatSlider(min=0.1, max=5.0, step=0.1, value=2.0, description='Depth [m]:',readout_format='.1f',layout=layout,style=style)\n",
"airTemp=widgets.FloatSlider(min=-40, max=35, step=1.0, value=10.0, description='Air temp.[°C]:',readout_format='.0f',layout=layout,style=style) \n",
"hotAirTemp=widgets.FloatSlider(min=-40, max=55, step=1.0, value=35.0, description='Hot air temp.[°C]:',readout_format='.0f',layout=layout,style=style)\n",
"coatDens=widgets.FloatSlider(min=1, max=50, step=1.0, value=15.0, description='Coating density [g/m2]:',readout_format='.0f',layout=layout,style=style) \n",
"tapeDens=widgets.FloatSlider(min=0.5, max=10, step=0.5, value=2.0, description='Adh. tape density [g/m]:',readout_format='.1f',layout=layout,style=style) \n",
"payloadWeight=widgets.FloatSlider(min=0.0, max=1000.0, step=1, value=0.0, description='Payload weight [g]:',readout_format='.0f',layout=layout,style=style)\n",
"\n",
"\n",
"w = widgets.interactive_output(f, {\n",
" 'width' : width,\n",
" 'height' : height,\n",
" 'depth' : depth,\n",
" 'airTemp' : airTemp,\n",
" 'hotAirTemp' : hotAirTemp,\n",
" 'coatDens' : coatDens,\n",
" 'tapeDens' : tapeDens,\n",
" 'payloadWeight' : payloadWeight\n",
" }\n",
" )\n",
"\n",
"\n",
"widgets.VBox([width, height, depth, airTemp, hotAirTemp, coatDens, tapeDens, payloadWeight, w])\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7ff11053-436e-4770-bdae-62224e52f168",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"extensions": {
"jupyter_dashboards": {
"activeView": "grid_default",
"version": 1,
"views": {
"grid_default": {
"cellMargin": 2,
"defaultCellHeight": 60,
"maxColumns": 12,
"name": "grid",
"type": "grid"
}
}
}
},
"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.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}