КП: Эффект Магнуса

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
А.М. Кривцов > Теоретическая механика > Курсовые проекты ТМ 2015 > Эффект Магнуса


Курсовой проект по Теоретической механике

Исполнитель: Шварёв Николай

Группа: 09 (23604)

Семестр: весна 2015

Сила Магнуса[1]

Аннотация проекта[править]

Данный проект посвящен изучению эффекта Магнуса, возникающего в различных видах спорта, а также использующегося в баллистике, летательных аппаратах и кораблях.В ходе работы над проектом были рассмотрены траектории полета мяча и цилиндра в зависимости от различных начальных параметров (радиуса, динамической вязкости среды, плотности воздуха, линейной и угловой скорости). Программа написана на языке JavaScript с использование библиотеки Three.js.

Формулировка задачи[править]

Построение и исследование математической модели движения объекта (в нашем случае - футбольного мяча и цилиндра), получение уравнения его движения и построение траектории в трехмерном пространстве с учётом различных внешних факторов, влияющих на движение, таких как сила сопротивления воздуха и эффект Магнуса.

Общие сведения по теме[править]

Пример влияния силы Магнуса на траекторию движения мяча[1]

Эффект Магнуса - образование подъемной силы, действующей на вращающееся тело при обтекании его потоком жидкости или газа, широко использующейся в спорте, баллистике, летательных аппаратах и кораблях. [2]

Данный эффект возникает в результате разности давлений (в соответствии с законом Бернулли[3]) на стенках объекта из-за разных скоростей движения воздуха. Возникающий дисбаланс заставляет объект отклоняться.

Решение[править]

Силу сопротивления воздуха для мяча будем считать с помощью закона Стокса[4]:

[math]\vec{F} = -6πrη\vec{v} [/math] , где

[math]\vec{F}[/math] - сила Стокса,

[math]r[/math] - радиус мяча,

[math]η[/math] - динамическая вязкость среды,

[math]\vec{v}[/math] - скорость мяча.


Силу Магнуса примем вида[5]:

[math]\vec{F} = 2Sρr\vec{u}\times\vec{ω} [/math] , где

[math]\vec{F}[/math] - сила Магнуса,

[math]S[/math] - площадь действия силы,

[math]ρ[/math] - плотность воздуха,

[math]r[/math] - радиус,

[math]\vec{u}[/math] - относительная скорость,

[math]\vec{ω}[/math] - угловая скорость.


Применив метод Эйлера, получим формулы для нахождения скорости и координаты мяча:

[math] \begin{cases} v_x^{i+1} = v_x^i + (-6πrηv_x^i/m + 2Sρr(u_y^iω_z - u_z^iω_y)/m)\Delta t \\ v_y^{i+1} = v_y^i + (-6πrηv_y^i/m + 2Sρr(u_z^iω_w - u_x^iω_z)/m)\Delta t \\ v_z^{i+1} = v_z^i + (-6πrηv_z^i/m - g + 2Sρr(u_x^iω_y - u_y^iω_x)/m)\Delta t \\ \end{cases} [/math]

[math] \begin{cases} x^{i+1} = x^i + v_x^i\Delta t \\ y^{i+1} = y^i + v_y^i\Delta t \\ z^{i+1} = z^i + v_z^i\Delta t \\ \end{cases} [/math]


Реализация алгоритма.

Возможности программы:

  • поочередный запуск мяча и цилиндра,
  • изменение параметров как в начале, так и во время полета,
  • просмотр картинки в трехмерном изображении с помощью мыши
  • сброс всех данных до начальных при нажатии кнопки "Reload"


Текст программы на языке JavaScript:

Файл "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. Была построена траектория движения и произведены эксперименты, результаты которых находятся в таблице ниже:

Шар:

[math]V_x[/math] [math]V_y[/math] [math]V_z[/math] [math]ω_x[/math] [math]ω_y[/math] [math]ω_z[/math] [math]m[/math] [math]r[/math] [math]Δ_y[/math]
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

Цилиндр:

[math]V_x[/math] [math]V_y[/math] [math]V_z[/math] [math]ω_x[/math] [math]ω_y[/math] [math]ω_z[/math] [math]m[/math] [math]r[/math] [math]h[/math] [math]Δ_y[/math]
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

где [math]V_x[/math], [math]V_y[/math], [math]V_z[/math] - начальные линейные скорости, [math]ω_x[/math], [math]ω_y[/math], [math]ω_z[/math] - начальные угловые скорости, [math]m[/math] - масса объекта, [math]r[/math] - радиус объекта, [math]h[/math] - высота цилиндра, а [math]Δ_y[/math] - полученное смещение по оси [math]y[/math].

Вывод: Исходя из численных данных, полученных после проведения экспериментов, можно сделать вывод, что относительное смещение зависит от угловой скорости, радиуса, массы и силы тяжести, но не зависит от линейной скорости. Например, при уменьшении угловой скорости в 2 раза следует уменьшение относительного отклонения в ~2 раза, а при уменьшении линейной скорости в 2 раза относительное отклонение остается таким же.



Скачать отчет: doc.
Скачать презентацию: pptx.

Ссылки по теме[править]

См. также[править]