346 wiersze
12 KiB
Plaintext
346 wiersze
12 KiB
Plaintext
{
|
||
"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⋅kg−1⋅K−1]\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
|
||
}
|