КП: Эффект Магнуса
Курсовой проект по Теоретической механике
Исполнитель: Шварёв Николай
Группа: 09 (23604)
Семестр: весна 2015
Содержание
Аннотация проекта[править]
Данный проект посвящен изучению эффекта Магнуса, возникающего в различных видах спорта, а также использующегося в баллистике, летательных аппаратах и кораблях.В ходе работы над проектом были рассмотрены траектории полета мяча и цилиндра в зависимости от различных начальных параметров (радиуса, динамической вязкости среды, плотности воздуха, линейной и угловой скорости). Программа написана на языке JavaScript с использование библиотеки Three.js.
Формулировка задачи[править]
Построение и исследование математической модели движения объекта (в нашем случае - футбольного мяча и цилиндра), получение уравнения его движения и построение траектории в трехмерном пространстве с учётом различных внешних факторов, влияющих на движение, таких как сила сопротивления воздуха и эффект Магнуса.
Общие сведения по теме[править]
Эффект Магнуса - образование подъемной силы, действующей на вращающееся тело при обтекании его потоком жидкости или газа, широко использующейся в спорте, баллистике, летательных аппаратах и кораблях. [2]
Данный эффект возникает в результате разности давлений (в соответствии с законом Бернулли[3]) на стенках объекта из-за разных скоростей движения воздуха. Возникающий дисбаланс заставляет объект отклоняться.
Решение[править]
Силу сопротивления воздуха для мяча будем считать с помощью закона Стокса[4]:
, где
- сила Стокса,
- радиус мяча,
- динамическая вязкость среды,
- скорость мяча.
Силу Магнуса примем вида[5]:
, где
- сила Магнуса,
- площадь действия силы,
- плотность воздуха,
- радиус,
- относительная скорость,
- угловая скорость.
Применив метод Эйлера, получим формулы для нахождения скорости и координаты мяча:
Реализация алгоритма.
Возможности программы:
- поочередный запуск мяча и цилиндра,
- изменение параметров как в начале, так и во время полета,
- просмотр картинки в трехмерном изображении с помощью мыши
- сброс всех данных до начальных при нажатии кнопки "Reload"
Файл "4.js"
1 function main()
2 {
3 var scene = new THREE.Scene();
4 var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
5 var render = new THREE.WebGLRenderer();
6 render.setClearColor(0x87CEFA, 1);
7 render.setSize(800, 400);
8
9 var axes = new THREE.AxisHelper(20);
10 scene.add(axes);
11
12 /**
13 var planeGeometry = new THREE.PlaneGeometry(105,68,50,1);
14 */
15 var planeGeometry = new THREE.PlaneGeometry(1000,500,50,1);
16 var planeMaterial = new THREE.MeshLambertMaterial({color:0x068000});
17 var plane = new THREE.Mesh(planeGeometry, planeMaterial);
18 plane.position.x=0;
19 plane.position.y=0;
20 plane.position.z=-0.11;
21
22 scene.add(plane);
23
24 var ballGeometry = new THREE.SphereGeometry( 0.11, 16, 16 );
25 var ballMaterial = new THREE.MeshBasicMaterial( {color: 0xffff00,wireframe:true} );
26 var ball = new THREE.Mesh( ballGeometry, ballMaterial );
27 scene.add( ball );
28 ball.castShadow = true;
29
30
31 var cylinderGeometry = new THREE.CylinderGeometry(0.11,0.11,1,16);
32 var cylinderMaterial = new THREE.MeshLambertMaterial({color:0xffff00});
33 var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
34 cylinder.position.x=0;
35 cylinder.position.y=0;
36 cylinder.position.z=0;
37 scene.add(cylinder);
38 cylinder.castShadow = true;
39
40 var trajectoryGeometryB = new THREE.SphereGeometry(0.05, 16, 16);
41 var trajectoryMaterialB = new THREE.MeshBasicMaterial( {color: 0x000000,wireframe:true} );
42
43 var trajectoryGeometryC = new THREE.SphereGeometry(0.05, 16, 16);
44 var trajectoryMaterialC = new THREE.MeshBasicMaterial( {color: 0xFF0000,wireframe:true} );
45
46 var traMaterialB = new THREE.MeshBasicMaterial({color: 0xffffff});
47 var traGeometryB = new THREE.CircleGeometry( 0.05, 16);
48
49 var traMaterialC = new THREE.MeshBasicMaterial({color: 0xFF9900});
50 var traGeometryC = new THREE.CircleGeometry( 0.05, 16);
51
52
53 /**
54 var cubeGeometry = new THREE.CubeGeometry(4,4,4);
55 var cubeMesh = new THREE.MeshLambertMaterial({color:0xff0000, wireframe:false});
56 var cube = new THREE.Mesh(cubeGeometry, cubeMesh);
57 cube.position.x=-4;
58 cube.position.y=3;
59 cube.position.z=0;
60 scene.add(cube);
61
62
63 var cylinderGeometry = new THREE.CylinderGeometry(4,4,5,16);
64 var cylinderMaterial = new THREE.MeshLambertMaterial({color:0xaaee00});
65 var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
66 cylinder.position.x=10;
67 cylinder.position.y=10;
68 cylinder.position.z=0;
69
70 scene.add(cylinder);
71 */
72
73
74
75
76 var spotLight = new THREE.SpotLight(0xffffff);
77 spotLight.position.set(0,0,1500);
78 scene.add(spotLight);
79
80
81 spotLight.castShadow = true;
82
83
84
85 render.shadowMapEnabled = true;
86 plane.receiveShadow = true;
87
88 /**
89 cube.castShadow = true;
90 cylinder.castShadow = true;
91 */
92
93
94
95 var a = new THREE.Vector3( 5, 2, -1 );
96 var b = new THREE.Vector3( -1, 1, 1 );
97
98 var c = new THREE.Vector3();
99 c.crossVectors( a, b );
100
101 camera.position.x= -30;
102 camera.position.y= 0;
103 camera.position.z= 60;
104 camera.lookAt(c);
105
106 camera.lookAt(scene.position);
107 $("#webGL").append(render.domElement);
108
109
110
111 var controls = new function() {
112 this.WindPowerX = 0;
113 this.WindPowerY = 0;
114 this.WindPowerZ = 0;
115 this.Mass = 0.45;
116 this.Radius = 0.11;
117 this.Height = 0.22;
118 this.Viscosity = 0.000178;
119 this.AirDensity = 1.2754;
120 this.g = 9.8
121 this.Vx = 15;
122 this.Vy = 0;
123 this.Vz = 5;
124 this.OmegaX = 0;
125 this.OmegaY = 0;
126 this.OmegaZ = -10;
127 }
128 var gui = new dat.GUI();
129 gui.add(controls, 'WindPowerX',-10,10);
130 gui.add(controls, 'WindPowerY',-10,10);
131 gui.add(controls, 'WindPowerZ',-10,10);
132 gui.add(controls, 'Mass',0.41,0.45);
133 gui.add(controls, 'Radius',0.01,0.21);
134 gui.add(controls, 'Height',0.1, 1);
135 gui.add(controls, 'Viscosity',0.00001, 0.001)
136 gui.add(controls, 'AirDensity',1, 1000)
137 gui.add(controls, 'g',0, 20)
138 gui.add(controls, 'Vx',0,40);
139 gui.add(controls, 'Vy',0,40);
140 gui.add(controls, 'Vz',0,40);
141 gui.add(controls, 'OmegaX',-10,10);
142 gui.add(controls, 'OmegaY',-10,10);
143 gui.add(controls, 'OmegaZ',-10,10);
144
145
146 contr = new THREE.OrbitControls(camera);
147 contr.dumping = 0.2;
148
149
150
151 /**contr = new THREE.TrackballControls(camera);
152 contr.rotateSpeed = 1.0;
153 contr.zoomSpeed = 1.2;
154 contr.panSpeed = 0.8;
155 contr.noZoom = false;
156 contr.noPan = false;
157 contr.staticMoving = true;
158 contr.dynamicDampingFactor = 0.3;
159 contr.keys = [65,83,68];
160 */
161
162
163 /**window.addEventListener('resize',onWindowResize,false);
164 function onWindowResize()
165 {
166 camera.aspect = window.innerWidth/window.innerHeight;
167 camera.updateProjectionMatrix();
168 render.setSize(window.innerWidth,window.innerHeight);
169
170 renderer();
171 }
172 */
173
174 var stats = initStats();
175 var step = 0;
176
177
178 Vx = 0;
179 Vy = 0;
180 Vz = 0;
181 Mass = 0;
182 Viscosity = 0;
183 dt = 0.01;
184 Radius = 0;
185 g = 0;
186 WindX = 0;
187 WindY = 0;
188 WindZ = 0;
189 AirDensity = 0;
190
191 Height = 1;
192
193 var VxB =controls.Vx;
194 var VxC =controls.Vx;
195 var VyB =controls.Vy;
196 var VyC =controls.Vy;
197 var VzB =controls.Vz;
198 var VzC =controls.Vz;
199
200 OmegaXB = controls.OmegaX;
201 OmegaXC = controls.OmegaX;
202 OmegaYB = controls.OmegaY;
203 OmegaYC = controls.OmegaY;
204 OmegaZB = controls.OmegaZ;
205 OmegaZC = controls.OmegaZ;
206
207
208 pppB = 0;
209 pppC = 0;
210 kkk = 0;
211
212 function renderer()
213 {
214 /**
215 cube.rotation.x+=controls.rotationSpeed;
216 cube.rotation.y+=controls.rotationSpeed;
217 cube.rotation.z+=controls.rotationSpeed;
218
219 cylinder.position.x = 20+(10*(Math.cos(step)));
220 cylinder.position.y = 2+(10*(Math.abs(Math.sin(step))));
221
222
223 */
224
225 if (pppB == 0)
226 {
227 VxB+=controls.Vx;
228 VyB+=controls.Vy;
229 VzB+=controls.Vz;
230 WindX = controls.WindPowerX;
231 WindY = controls.WindPowerY;
232 WindZ = controls.WindPowerZ;
233
234 OmegaXB = controls.OmegaX;
235 OmegaYB = controls.OmegaY;
236 OmegaZB = controls.OmegaZ;
237
238
239 pppB = 1;
240
241 }
242
243 UxB = VxB - WindX;
244 UyB = VyB - WindY;
245 UzB = VzB - WindZ;
246
247 Mass=controls.Mass;
248 Radius=controls.Radius;
249 Viscosity = controls.Viscosity;
250 g = controls.g;
251
252 AirDensity = controls.AirDensity;
253
254
255 if (ball.position.z >= 0)
256 {
257
258 /**
259 VxB += (-6*Math.PI*Viscosity*Radius*VxB/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UyB*OmegaZB - UzB*OmegaYB)/Mass)*dt;
260 VyB += (-6*Math.PI*Viscosity*Radius*VyB/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UzB*OmegaXB - UxB*OmegaZB)/Mass )*dt;
261 VzB += (-6*Math.PI*Viscosity*Radius*VzB/Mass - g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxB*OmegaYB - UyB*OmegaXB)/Mass)*dt;
262
263 OmegaXB += -6*Math.PI*Viscosity*Radius*OmegaXB*Radius/Mass;
264 OmegaYB += -6*Math.PI*Viscosity*Radius*OmegaYB*Radius/Mass;
265 OmegaZB += -6*Math.PI*Viscosity*Radius*OmegaZB*Radius/Mass;
266
267 */
268
269 VxB += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UyB*OmegaZB - UzB*OmegaYB)/Mass)*dt;
270 VyB += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UzB*OmegaXB - UxB*OmegaZB)/Mass )*dt;
271 VzB += (-g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxB*OmegaYB - UyB*OmegaXB)/Mass)*dt;
272
273 ball.position.x += VxB*dt;
274 ball.position.y += VyB*dt;
275 ball.position.z += VzB*dt;
276
277
278
279 ball.rotation.x += OmegaXB*dt;
280 ball.rotation.y += OmegaYB*dt;
281 ball.rotation.z += OmegaZB*dt;
282
283 var trajectoryB = new THREE.Mesh(trajectoryGeometryB, trajectoryMaterialB);
284 trajectoryB.position.x = ball.position.x;
285 trajectoryB.position.y = ball.position.y;
286 trajectoryB.position.z = ball.position.z;
287
288 scene.add( trajectoryB );
289
290
291 var traB = new THREE.Mesh( traGeometryB, traMaterialB);
292 traB.position.x = ball.position.x;
293 traB.position.y = ball.position.y;
294 traB.position.z = 0;
295 scene.add(traB);
296
297 document.getElementById("td1").innerHTML = ball.position.y ;
298 document.getElementById("td2").innerHTML = ball.position.x ;
299
300 }
301
302 requestAnimationFrame(renderer);
303
304 contr.update();
305
306 render.render(scene,camera);
307
308
309
310
311 }
312
313 alpha1 = 0;
314 alpha2 = 0;
315 alpha3 = 0;
316 rot1 = 0;
317 rot2 = 0;
318 rot3 = 0;
319
320 function renderer2()
321 {
322
323
324 if (pppC == 0)
325 {
326 VyC+=controls.Vy;
327 VxC+=controls.Vx;
328 VzC+=controls.Vz;
329 WindX = controls.WindPowerX;
330 WindY = controls.WindPowerY;
331 WindZ = controls.WindPowerZ;
332
333 OmegaXC = controls.OmegaX;
334 OmegaYC = controls.OmegaY;
335 OmegaZC = controls.OmegaZ;
336
337
338 pppC = 1;
339
340 }
341
342 UxC = VxC - WindX;
343 UyC = VyC - WindY;
344 UzC = VzC - WindZ;
345
346 Mass=controls.Mass;
347 Radius=controls.Radius;
348 Viscosity = controls.Viscosity;
349 g = controls.g;
350 Height = controls.Height;
351 AirDensity = controls.AirDensity;
352
353 var cylinderGeometry = new THREE.CylinderGeometry(2*Radius,2*Radius, Height, 16);
354
355 cylinder.geometry = cylinderGeometry;
356
357
358 if (cylinder.position.z >= 0)
359 {
360 /**
361 VxC += (-6*Math.PI*Viscosity*Radius*VxC/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
362 VyC += (-6*Math.PI*Viscosity*Radius*VyC/Mass + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
363 VzC += (-6*Math.PI*Viscosity*Radius*VzC/Mass - g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
364
365 OmegaXC += -6*Math.PI*Viscosity*Radius*OmegaXC*Radius/Mass;
366 OmegaYC += -6*Math.PI*Viscosity*Radius*OmegaYC*Radius/Mass;
367 OmegaZC += -6*Math.PI*Viscosity*Radius*OmegaZC*Radius/Mass;
368 */
369 /**
370 VxC += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
371 VyC += (2*Math.PI*AirDensity*Radius*Radius*Radius*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
372 VzC += (-g + 2*Math.PI*AirDensity*Radius*Radius*Radius*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
373 */
374
375
376 alpha1 = (cylinder.rotation.x - rot1)/(2*Math.PI);
377 alpha2 = (cylinder.rotation.y - rot2)/(2*Math.PI);
378 alpha3 = (cylinder.rotation.z - rot3)/(2*Math.PI);
379
380 rot1 = cylinder.rotation.x;
381 rot2 = cylinder.rotation.y;
382 rot3 = cylinder.rotation.z;
383
384 VxC += (2*AirDensity*Radius*(2*Radius*Height*Math.cos(alpha1) + Math.PI*Radius*Radius*Math.sin(alpha1) )*(UyC*OmegaZC - UzC*OmegaYC)/Mass)*dt;
385 VyC += (2*AirDensity*Radius*(2*Radius*Height*Math.sin(alpha2) + Math.PI*Radius*Radius*Math.cos(alpha2))*(UzC*OmegaXC - UxC*OmegaZC)/Mass )*dt;
386 VzC += (-g + 2*AirDensity*Radius*(2*Radius*Height*Math.cos(alpha3) + Math.PI*Radius*Radius*Math.sin(alpha3))*(UxC*OmegaYC - UyC*OmegaXC)/Mass)*dt;
387
388 cylinder.position.x += VxC*dt;
389 cylinder.position.y += VyC*dt;
390 cylinder.position.z += VzC*dt;
391
392 cylinder.rotation.x += OmegaXC*dt;
393 cylinder.rotation.y += OmegaYC*dt;
394 cylinder.rotation.z += OmegaZC*dt;
395
396
397
398 var trajectoryC = new THREE.Mesh(trajectoryGeometryC, trajectoryMaterialC);
399 trajectoryC.position.x = cylinder.position.x;
400 trajectoryC.position.y = cylinder.position.y;
401 trajectoryC.position.z = cylinder.position.z;
402
403 scene.add( trajectoryC );
404
405 var traC = new THREE.Mesh( traGeometryC, traMaterialC);
406 traC.position.x = cylinder.position.x;
407 traC.position.y = cylinder.position.y;
408 traC.position.z = 0;
409 scene.add(traC);
410
411 document.getElementById("td3").innerHTML = cylinder.position.y ;
412 document.getElementById("td4").innerHTML = cylinder.position.x;
413
414 }
415
416 requestAnimationFrame(renderer2);
417
418 contr.update();
419
420 render.render(scene,camera);
421
422 }
423
424 this.start = renderer;
425 this.start2 = renderer2;
426
427
428
429 }
430 function initStats()
431 {
432 var stats = new Stats();
433 stats.setMode(0);
434 stats.domElement.style.position='absolute';
435 stats.domElement.style.left = '0px';
436 stats.domElement.style.top = '0px';
437 $("#Stats").append(stats.domElement);
438 return stats;
439 }
Обсуждение результатов и выводы[править]
Разработанный алгоритм был реализован в среде программирования Javascript с использование библиотеки Three.js. Была построена траектория движения и произведены эксперименты, результаты которых находятся в таблице ниже:
Шар:
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 14.585 |
15 | 0 | 5 | 0 | 0 | -10 | 0.41 | 0.11 | 15.945 |
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.01 | 0.011 |
15 | 0 | 5 | 0 | 0 | -5 | 0.45 | 0.11 | 7.399 |
7.5 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 7.292 |
Цилиндр:
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 0.22 | 14.508 |
15 | 0 | 5 | 0 | 0 | -10 | 0.41 | 0.11 | 0.22 | 15.844 |
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.01 | 0.22 | 0.011 |
15 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 1 | 13.287 |
15 | 0 | 5 | 0 | 0 | -5 | 0.45 | 0.11 | 0.22 | 7.389 |
7.5 | 0 | 5 | 0 | 0 | -10 | 0.45 | 0.11 | 0.22 | 7.254 |
где
, , - начальные линейные скорости, , , - начальные угловые скорости, - масса объекта, - радиус объекта, - высота цилиндра, а - полученное смещение по оси .Вывод: Исходя из численных данных, полученных после проведения экспериментов, можно сделать вывод, что относительное смещение зависит от угловой скорости, радиуса, массы и силы тяжести, но не зависит от линейной скорости. Например, при уменьшении угловой скорости в 2 раза следует уменьшение относительного отклонения в ~2 раза, а при уменьшении линейной скорости в 2 раза относительное отклонение остается таким же.
Скачать отчет: doc.
Скачать презентацию: pptx.