daniel-dobos commited on
Commit
8495b01
·
1 Parent(s): b4a5d15

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +16 -0
  2. app.ipynb +317 -0
  3. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+ RUN python3 -m pip install --no-cache-dir --upgrade pip
7
+ RUN python3 -m pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["panel", "serve", "/code/manganite-demo.ipynb", "--address", "0.0.0.0", "--port", "7860", "--allow-websocket-origin", "*"]
12
+
13
+ RUN mkdir /.cache
14
+ RUN chmod 777 /.cache
15
+ RUN mkdir .chroma
16
+ RUN chmod 777 .chroma
app.ipynb ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import manganite\n",
10
+ "%load_ext manganite"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {},
16
+ "source": [
17
+ "# Airfoil Analysis\n",
18
+ "# with [AeroSandbox](https://github.com/peterdsharpe/AeroSandbox) and [Manganite](https://github.com/LCL-CAVE/manganite)\n",
19
+ "\n",
20
+ "## Description\n",
21
+ "\n",
22
+ "The Airfoil Design Demonstration Dashboard is a web-based showcase that provides a glimpse into the capabilities of airfoil analysis within a browser environment. It is built upon the open-source repository [AeroSandbox](https://github.com/peterdsharpe/Automotive-Airfoil-Design/) and serves as a demonstration of what's possible in the realm of virtual airfoil exploration.\n",
23
+ "\n",
24
+ "### Key Features\n",
25
+ "\n",
26
+ "1. **Geometry Visualization:** Explore an interactive airfoil geometry, pre-defined for demonstration purposes. Observe how changes in shape and size can impact aerodynamic behavior.\n",
27
+ "\n",
28
+ "2. **Simplified Angle of Attack:** Adjust the angle of attack within a limited range to see the immediate effects on lift and drag forces. \n",
29
+ "\n",
30
+ "3. **Kulfan Coordinates:** This demonstration employs Kulfan coordinates for the representation of airfoil shapes, providing insight into how airfoil data can be structured and analyzed.\n",
31
+ "\n",
32
+ "4. **Basic Constant Display:** View simplified constant values such as lift coefficient (CL), drag coefficient (CD), and moment coefficient (CM).\n",
33
+ "\n",
34
+ "5. **Visualization:** Visualize how changes in airfoil geometry and angle of attack influence aerodynamic characteristics."
35
+ ]
36
+ },
37
+ {
38
+ "cell_type": "code",
39
+ "execution_count": null,
40
+ "metadata": {},
41
+ "outputs": [],
42
+ "source": [
43
+ "import plotly.express as px\n",
44
+ "import plotly.graph_objects as go\n",
45
+ "import aerosandbox as asb\n",
46
+ "import aerosandbox.numpy as np\n",
47
+ "import copy\n",
48
+ "import plotly.figure_factory as ff\n",
49
+ "import pandas as pd"
50
+ ]
51
+ },
52
+ {
53
+ "cell_type": "code",
54
+ "execution_count": null,
55
+ "metadata": {},
56
+ "outputs": [],
57
+ "source": [
58
+ "%%mnn widget --type slider -20:20:0.1 --tab \"Operating Conditions\" --header \"Angle of Attack\" --var alpha\n",
59
+ "alpha = 8.7"
60
+ ]
61
+ },
62
+ {
63
+ "cell_type": "code",
64
+ "execution_count": null,
65
+ "metadata": {},
66
+ "outputs": [],
67
+ "source": [
68
+ "streamline_density = 1\n",
69
+ "height = 0\n",
70
+ "ground_effect = False"
71
+ ]
72
+ },
73
+ {
74
+ "cell_type": "code",
75
+ "execution_count": null,
76
+ "metadata": {},
77
+ "outputs": [],
78
+ "source": [
79
+ "%%mnn widget --type slider -0.1:0.7:0.01 --tab \"Shape Parameters\" --header \"Upper surface 1\" --var upper_1 --position 0 0 2\n",
80
+ "upper_1 = 0.25"
81
+ ]
82
+ },
83
+ {
84
+ "cell_type": "code",
85
+ "execution_count": null,
86
+ "metadata": {},
87
+ "outputs": [],
88
+ "source": [
89
+ "%%mnn widget --type slider -0.1:0.7:0.01 --tab \"Shape Parameters\" --header \"Upper surface 2\" --var upper_2 --position 0 2 2\n",
90
+ "upper_2 = 0.47"
91
+ ]
92
+ },
93
+ {
94
+ "cell_type": "code",
95
+ "execution_count": null,
96
+ "metadata": {},
97
+ "outputs": [],
98
+ "source": [
99
+ "%%mnn widget --type slider -0.1:0.7:0.01 --tab \"Shape Parameters\" --header \"Upper surface 3\" --var upper_3 --position 0 4 2\n",
100
+ "upper_3 = 0.024"
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "code",
105
+ "execution_count": null,
106
+ "metadata": {},
107
+ "outputs": [],
108
+ "source": [
109
+ "%%mnn widget --type slider -0.5:0.3:0.01 --tab \"Shape Parameters\" --header \"Lower surface 1\" --var lower_1 --position 1 0 2\n",
110
+ "lower_1 = -0.11"
111
+ ]
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "execution_count": null,
116
+ "metadata": {},
117
+ "outputs": [],
118
+ "source": [
119
+ "%%mnn widget --type slider 0:0.7:0.01 --tab \"Shape Parameters\" --header \"Lower surface 2\" --var lower_2 --position 1 2 2\n",
120
+ "lower_2 = 0.06"
121
+ ]
122
+ },
123
+ {
124
+ "cell_type": "code",
125
+ "execution_count": null,
126
+ "metadata": {},
127
+ "outputs": [],
128
+ "source": [
129
+ "%%mnn widget --type slider 0:0.7:0.01 --tab \"Shape Parameters\" --header \"Lower surface 3\" --var lower_3 --position 1 4 2\n",
130
+ "lower_3 = -0.06"
131
+ ]
132
+ },
133
+ {
134
+ "cell_type": "code",
135
+ "execution_count": null,
136
+ "metadata": {},
137
+ "outputs": [],
138
+ "source": [
139
+ "def display_graph(n_clicks, alpha, height, streamline_density, kulfan_upper, kulfan_lower, analyze_button_pressed = False):\n",
140
+ "\n",
141
+ " ### Start constructing the figure\n",
142
+ " airfoil = asb.Airfoil(\n",
143
+ " coordinates=asb.get_kulfan_coordinates(\n",
144
+ " lower_weights=np.array(lower_values),\n",
145
+ " upper_weights=np.array(upper_values),\n",
146
+ " TE_thickness=0,\n",
147
+ " enforce_continuous_LE_radius=False,\n",
148
+ " n_points_per_side=200\n",
149
+ " )\n",
150
+ " )\n",
151
+ "\n",
152
+ " # ### Do coordinates output\n",
153
+ " # coordinates_output = \"\\n\".join(\n",
154
+ " # [\"```\"] +\n",
155
+ " # [\"AeroSandbox Airfoil\"] +\n",
156
+ " # [\"\\t%f\\t%f\" % tuple(coordinate) for coordinate in airfoil.coordinates] +\n",
157
+ " # [\"```\"]\n",
158
+ " # )\n",
159
+ "\n",
160
+ " ### Continue doing the airfoil things\n",
161
+ " airfoil = airfoil.rotate(angle=-np.radians(alpha))\n",
162
+ " airfoil = airfoil.translate(\n",
163
+ " 0,\n",
164
+ " height + 0.5 * np.sind(alpha)\n",
165
+ " )\n",
166
+ " fig = go.Figure()\n",
167
+ " fig.add_trace(\n",
168
+ " go.Scatter(\n",
169
+ " x=airfoil.x(),\n",
170
+ " y=airfoil.y(),\n",
171
+ " mode=\"lines\",\n",
172
+ " name=\"Airfoil\",\n",
173
+ " fill=\"toself\",\n",
174
+ " line=dict(\n",
175
+ " color=\"blue\"\n",
176
+ " )\n",
177
+ " )\n",
178
+ " )\n",
179
+ "\n",
180
+ " ### Default text output\n",
181
+ " text_output = 'Click \"Analyze\" to compute aerodynamics!'\n",
182
+ " output = text_output\n",
183
+ "\n",
184
+ " xrng = (-0.5, 1.5)\n",
185
+ " yrng = (-0.6, 0.6) if not ground_effect else (0, 1.2)\n",
186
+ "\n",
187
+ " if analyze_button_pressed:\n",
188
+ "\n",
189
+ " analysis = asb.AirfoilInviscid(\n",
190
+ " airfoil=airfoil.repanel(50),\n",
191
+ " op_point=asb.OperatingPoint(\n",
192
+ " velocity=1,\n",
193
+ " alpha=0,\n",
194
+ " ),\n",
195
+ " ground_effect=ground_effect\n",
196
+ " )\n",
197
+ "\n",
198
+ " x = np.linspace(*xrng, 100)\n",
199
+ " y = np.linspace(*yrng, 100)\n",
200
+ " X, Y = np.meshgrid(x, y)\n",
201
+ " u, v = analysis.calculate_velocity(\n",
202
+ " x_field=X.flatten(),\n",
203
+ " y_field=Y.flatten()\n",
204
+ " )\n",
205
+ " U = u.reshape(X.shape)\n",
206
+ " V = v.reshape(Y.shape)\n",
207
+ "\n",
208
+ " streamline_fig = ff.create_streamline(\n",
209
+ " x, y, U, V,\n",
210
+ " arrow_scale=1e-16,\n",
211
+ " density=streamline_density,\n",
212
+ " line=dict(\n",
213
+ " color=\"#ff82a3\"\n",
214
+ " ),\n",
215
+ " name=\"Streamlines\"\n",
216
+ " )\n",
217
+ "\n",
218
+ " fig = go.Figure(\n",
219
+ " data=streamline_fig.data + fig.data\n",
220
+ " )\n",
221
+ "\n",
222
+ " output = pd.DataFrame(\n",
223
+ " {\n",
224
+ " \"Engineering Quantity\": [\n",
225
+ " \"C_L\"\n",
226
+ " ],\n",
227
+ " \"Value\" : [\n",
228
+ " f\"{analysis.Cl:.3f}\"\n",
229
+ " ]\n",
230
+ " }\n",
231
+ " )\n",
232
+ "\n",
233
+ " fig.update_layout(\n",
234
+ " xaxis_title=\"x/c\",\n",
235
+ " yaxis_title=\"y/c\",\n",
236
+ " showlegend=False,\n",
237
+ " yaxis=dict(scaleanchor=\"x\", scaleratio=1),\n",
238
+ " margin={'t': 0},\n",
239
+ " title=None,\n",
240
+ " )\n",
241
+ "\n",
242
+ " fig.update_xaxes(range=xrng)\n",
243
+ " fig.update_yaxes(range=yrng)\n",
244
+ "\n",
245
+ " return fig, output"
246
+ ]
247
+ },
248
+ {
249
+ "cell_type": "code",
250
+ "execution_count": null,
251
+ "metadata": {},
252
+ "outputs": [],
253
+ "source": [
254
+ "%%mnn widget --type plot --var aero_fig --tab \"Shape Parameters\" --header \"Airfoil Cross section\" --position 2 0 6\n",
255
+ "upper_values = [upper_1, upper_2,upper_3]\n",
256
+ "lower_values = [lower_1, lower_2, lower_3]\n",
257
+ "aero_fig, text_output = display_graph(1,alpha=alpha,height=0,streamline_density=streamline_density, kulfan_upper=upper_values, kulfan_lower=lower_values)\n"
258
+ ]
259
+ },
260
+ {
261
+ "cell_type": "code",
262
+ "execution_count": null,
263
+ "metadata": {},
264
+ "outputs": [],
265
+ "source": [
266
+ "%%mnn execute --on button \"Analyze\" --returns aero_performance\n",
267
+ "\n",
268
+ "aero_fig_lines, aero_performance = display_graph(1,alpha=alpha,height=0,streamline_density=streamline_density, kulfan_upper=upper_values, kulfan_lower=lower_values, analyze_button_pressed = True)\n"
269
+ ]
270
+ },
271
+ {
272
+ "cell_type": "code",
273
+ "execution_count": null,
274
+ "metadata": {},
275
+ "outputs": [],
276
+ "source": [
277
+ "%%mnn widget --type plot --var aero_fig_lines --tab \"Aerodynamic Performance\" --header \"Streamlines\" --position 0 0 6\n",
278
+ "\n",
279
+ "simu_ready = aero_performance\n",
280
+ "aero_fig_lines\n"
281
+ ]
282
+ },
283
+ {
284
+ "cell_type": "code",
285
+ "execution_count": null,
286
+ "metadata": {},
287
+ "outputs": [],
288
+ "source": [
289
+ "%%mnn widget --type table --tab \"Aerodynamic Performance\" --position 1 2 4 --header \"Metrics\" --var performance_values\n",
290
+ "\n",
291
+ "performance_values = aero_performance"
292
+ ]
293
+ }
294
+ ],
295
+ "metadata": {
296
+ "kernelspec": {
297
+ "display_name": "manganite-env",
298
+ "language": "python",
299
+ "name": "python3"
300
+ },
301
+ "language_info": {
302
+ "codemirror_mode": {
303
+ "name": "ipython",
304
+ "version": 3
305
+ },
306
+ "file_extension": ".py",
307
+ "mimetype": "text/x-python",
308
+ "name": "python",
309
+ "nbconvert_exporter": "python",
310
+ "pygments_lexer": "ipython3",
311
+ "version": "3.11.4"
312
+ },
313
+ "orig_nbformat": 4
314
+ },
315
+ "nbformat": 4,
316
+ "nbformat_minor": 2
317
+ }
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ panel
2
+ numpy
3
+ pandas
4
+ plotly
5
+ aerosandbox==3.0.0 # TODO fix a version
6
+ https://github.com/daniel-dobos-unilu/codespaces-manganite/raw/main/packages/manganite-0.0.3.tar.gz