Взаимодействие частиц (JavaScript) — различия между версиями
Материал из Department of Theoretical and Applied Mechanics
(→Скрипт) |
|||
(не показана 1 промежуточная версия этого же участника) | |||
Строка 1: | Строка 1: | ||
− | '''Исполнители:''' [ | + | '''Исполнители:''' [[ Егорова Екатерина]], [[Эдель Мария]] <br> |
'''Группа:''' 3630103/90003 <br> | '''Группа:''' 3630103/90003 <br> | ||
'''Семестр:''' весна 2020 года.<br> | '''Семестр:''' весна 2020 года.<br> | ||
Строка 17: | Строка 17: | ||
== Визуализация == | == Визуализация == | ||
{{#widget: Iframe | url=http://tm.spbstu.ru/htmlets/js2020/Egorova/mindex.html | width=700 | height=600 | border=0}} | {{#widget: Iframe | url=http://tm.spbstu.ru/htmlets/js2020/Egorova/mindex.html | width=700 | height=600 | border=0}} | ||
− | == | + | |
+ | ==Скрипт== | ||
<div class="mw-collapsible mw-collapsed"> | <div class="mw-collapsible mw-collapsed"> | ||
− | '''Код программы:''' <div class="mw-collapsible-content"> | + | '''Код программы на языке JavaScript:''' <div class="mw-collapsible-content"> |
− | {{# | + | <syntaxhighlight lang="javascript" line start="1" enclose="div"> |
+ | window.addEventListener('load', main, false); | ||
+ | function main(){ | ||
+ | |||
+ | var ctx = canvas_example.getContext('2d'); | ||
+ | var w = canvas_example.width; | ||
+ | var h = canvas_example.height; | ||
+ | |||
+ | |||
+ | function ball(x, y, r, m, Fx, Fy) { | ||
+ | this.x = x; | ||
+ | this.y = y; | ||
+ | this.vx = 0; | ||
+ | this.vy = 0; | ||
+ | this.r = r; | ||
+ | this.m = m; | ||
+ | this.Fx = Fx; | ||
+ | this.Fy = Fy; | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | var X_c = w/2; | ||
+ | var Y_c = h/3; | ||
+ | var Vy_c = 0; | ||
+ | |||
+ | var balls = []; | ||
+ | var r = 10; | ||
+ | |||
+ | |||
+ | for (var i=0; i<27; i++) { | ||
+ | balls.push(new ball(r+(w)*(i/27), h-r, r, 1, 0, 0)); | ||
+ | } | ||
+ | for (var i=0; i<26; i++) { | ||
+ | balls.push(new ball(2*r+(w)*(i/27), h-3*r, r, 1, 0, 0)); | ||
+ | } | ||
+ | for (var i=0; i<27; i++) { | ||
+ | balls.push(new ball(r+(w)*(i/27), h-5*r, r, 1, 0, 0)); | ||
+ | } | ||
+ | for (var i=0; i<26; i++) { | ||
+ | balls.push(new ball(2*r+(w)*(i/27), h-7*r, r, 1, 0, 0)); | ||
+ | } | ||
+ | for (var i=0; i<27; i++) { | ||
+ | balls.push(new ball(r+(w)*(i/27), h-9*r, r, 1, 0, 0)); | ||
+ | } | ||
+ | for (var i=0; i<26; i++) { | ||
+ | balls.push(new ball(2*r+(w)*(i/27), h-11*r, r, 1, 0, 0)); | ||
+ | } | ||
+ | for (var i=0; i<27; i++) { | ||
+ | balls.push(new ball(r+(w)*(i/27), h-13*r, r, 1, 0, 0)); | ||
+ | } | ||
+ | |||
+ | /*console.log(radius(R)); | ||
+ | console.log(svyaz(D)); | ||
+ | |||
+ | start.onclick = function() { | ||
+ | R = radius(); | ||
+ | D = svyaz();*/ | ||
+ | |||
+ | |||
+ | var r_ball = new ball(X_c, Y_c, R, 50, 0, 0) | ||
+ | r_ball.vy = 20; | ||
+ | var N = 159; | ||
+ | var a = 40; | ||
+ | var dt = 0.001; | ||
+ | var g = 1; | ||
+ | |||
+ | |||
+ | |||
+ | function draw() { | ||
+ | ctx.clearRect(0,0,w,h); | ||
+ | for (var i=0; i<N; i++) { | ||
+ | ctx.beginPath(); | ||
+ | ctx.arc(balls[i].x, balls[i].y, balls[i].r, 0, 2*Math.PI); | ||
+ | ctx.fillStyle = '#FF4500' | ||
+ | ctx.stroke(); | ||
+ | ctx.fill(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | ctx.beginPath(); | ||
+ | ctx.fillStyle = '#0000FF' | ||
+ | ctx.strokeStyle = '#000000'; | ||
+ | ctx.arc(r_ball.x, r_ball.y, r_ball.r, 0, 2*Math.PI); | ||
+ | ctx.stroke(); | ||
+ | ctx.fill(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | function phys() { | ||
+ | // обнуляем силы шариков | ||
+ | for (var i=0; i<N; i++) { | ||
+ | balls[i].Fx = 0; | ||
+ | balls[i].Fy = 0; | ||
+ | } | ||
+ | r_ball.Fx = 0; | ||
+ | r_ball.Fy = 0; | ||
+ | // считаем силы | ||
+ | for (var i=0; i<N-1; i++) { | ||
+ | for (var j=i+1; j<N; j++) { | ||
+ | var a = balls[i].r+balls[j].r; | ||
+ | var r2 = (balls[i].x-balls[j].x)*(balls[i].x-balls[j].x)+(balls[i].y-balls[j].y)*(balls[i].y-balls[j].y); | ||
+ | var Fx = 12*D/a/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].x-balls[j].x); | ||
+ | var Fy = 12*D/a/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].y-balls[j].y); | ||
+ | balls[i].Fx += Fx/balls[i].m; | ||
+ | balls[i].Fy += Fy/balls[i].m; | ||
+ | balls[j].Fx -= Fx/balls[j].m; | ||
+ | balls[j].Fy -= Fy/balls[j].m; | ||
+ | } | ||
+ | var a = balls[i].r+r_ball.r; | ||
+ | var r2 = (balls[i].x-r_ball.x)*(balls[i].x-r_ball.x)+(balls[i].y-r_ball.y)*(balls[i].y-r_ball.y); | ||
+ | if (r2<a*a) { | ||
+ | var Fx = 12*D/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].x-r_ball.x); | ||
+ | var Fy = 12*D/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].y-r_ball.y); | ||
+ | balls[i].Fx += Fx/balls[i].m; | ||
+ | balls[i].Fy += Fy/balls[i].m; | ||
+ | r_ball.Fx -= Fx/r_ball.m; | ||
+ | r_ball.Fy -= Fy/r_ball.m; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // двигаем шарики | ||
+ | for (var i=0; i<N; i++) { | ||
+ | balls[i].vx += balls[i].Fx*dt; | ||
+ | balls[i].vy += (balls[i].Fy+g)*dt; | ||
+ | balls[i].x += balls[i].vx*dt; | ||
+ | balls[i].y += balls[i].vy*dt; | ||
+ | |||
+ | if (balls[i].y < r) { | ||
+ | balls[i].y = r; | ||
+ | } | ||
+ | |||
+ | if (balls[i].y > h-r) { | ||
+ | balls[i].y = h-r; | ||
+ | } | ||
+ | |||
+ | if (balls[i].x>w-r) { | ||
+ | balls[i].x = w-r; | ||
+ | } | ||
+ | |||
+ | if (balls[i].x<r) { | ||
+ | balls[i].x = r; | ||
+ | } | ||
+ | var betta = 0.7; | ||
+ | r_ball.vx += (r_ball.Fx-betta*r_ball.vx)*dt; | ||
+ | r_ball.vy += (r_ball.Fy+g-betta*r_ball.vy)*dt; | ||
+ | r_ball.x += r_ball.vx*dt; | ||
+ | r_ball.y += r_ball.vy*dt; | ||
+ | |||
+ | if (r_ball.y < r) { | ||
+ | r_ball.vy *=-1; | ||
+ | } | ||
+ | |||
+ | if (r_ball.y > h-20) { | ||
+ | r_ball.vy *=-1; | ||
+ | } | ||
+ | |||
+ | if (r_ball.x>w-20) { | ||
+ | r_ball.vx *=-1; | ||
+ | } | ||
+ | |||
+ | if (r_ball.x<20) { | ||
+ | r_ball.vx *=-1; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | draw(); | ||
+ | |||
+ | function control() { | ||
+ | phys(); | ||
+ | draw(); | ||
+ | } | ||
+ | |||
+ | var timer = setInterval(control, 10); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | </div> |
Текущая версия на 21:56, 1 июня 2020
Исполнители: Егорова Екатерина, Эдель Мария
Группа: 3630103/90003
Семестр: весна 2020 года.
Постановка задачи[править]
Построить модель взаимодействия падающей частицы и препятствия в виде N неподвижных частиц.
Математическая модель[править]
В данной работе при подсчете сил взаимодействия частиц применялась модель парного силового потенциала взаимодействия Леннарда Джонса, описывающая зависимость энергии взаимодействия двух частиц от расстояния между ними.Эта модель позволяет достаточно реалистично передать свойства реального взаимодействия сферических неполярных молекул.
Парный силовой потенциал взаимодействия определяется формулой:
Входные данные
- Радиус падающего шарика: 20px
- Масса падающего шарика: 50
- Всего частиц: 160
Визуализация[править]
Скрипт[править]
Код программы на языке JavaScript:
1 window.addEventListener('load', main, false);
2 function main(){
3
4 var ctx = canvas_example.getContext('2d');
5 var w = canvas_example.width;
6 var h = canvas_example.height;
7
8
9 function ball(x, y, r, m, Fx, Fy) {
10 this.x = x;
11 this.y = y;
12 this.vx = 0;
13 this.vy = 0;
14 this.r = r;
15 this.m = m;
16 this.Fx = Fx;
17 this.Fy = Fy;
18 }
19
20
21
22 var X_c = w/2;
23 var Y_c = h/3;
24 var Vy_c = 0;
25
26 var balls = [];
27 var r = 10;
28
29
30 for (var i=0; i<27; i++) {
31 balls.push(new ball(r+(w)*(i/27), h-r, r, 1, 0, 0));
32 }
33 for (var i=0; i<26; i++) {
34 balls.push(new ball(2*r+(w)*(i/27), h-3*r, r, 1, 0, 0));
35 }
36 for (var i=0; i<27; i++) {
37 balls.push(new ball(r+(w)*(i/27), h-5*r, r, 1, 0, 0));
38 }
39 for (var i=0; i<26; i++) {
40 balls.push(new ball(2*r+(w)*(i/27), h-7*r, r, 1, 0, 0));
41 }
42 for (var i=0; i<27; i++) {
43 balls.push(new ball(r+(w)*(i/27), h-9*r, r, 1, 0, 0));
44 }
45 for (var i=0; i<26; i++) {
46 balls.push(new ball(2*r+(w)*(i/27), h-11*r, r, 1, 0, 0));
47 }
48 for (var i=0; i<27; i++) {
49 balls.push(new ball(r+(w)*(i/27), h-13*r, r, 1, 0, 0));
50 }
51
52 /*console.log(radius(R));
53 console.log(svyaz(D));
54
55 start.onclick = function() {
56 R = radius();
57 D = svyaz();*/
58
59
60 var r_ball = new ball(X_c, Y_c, R, 50, 0, 0)
61 r_ball.vy = 20;
62 var N = 159;
63 var a = 40;
64 var dt = 0.001;
65 var g = 1;
66
67
68
69 function draw() {
70 ctx.clearRect(0,0,w,h);
71 for (var i=0; i<N; i++) {
72 ctx.beginPath();
73 ctx.arc(balls[i].x, balls[i].y, balls[i].r, 0, 2*Math.PI);
74 ctx.fillStyle = '#FF4500'
75 ctx.stroke();
76 ctx.fill();
77
78 }
79
80
81 ctx.beginPath();
82 ctx.fillStyle = '#0000FF'
83 ctx.strokeStyle = '#000000';
84 ctx.arc(r_ball.x, r_ball.y, r_ball.r, 0, 2*Math.PI);
85 ctx.stroke();
86 ctx.fill();
87
88 }
89
90
91
92 function phys() {
93 // обнуляем силы шариков
94 for (var i=0; i<N; i++) {
95 balls[i].Fx = 0;
96 balls[i].Fy = 0;
97 }
98 r_ball.Fx = 0;
99 r_ball.Fy = 0;
100 // считаем силы
101 for (var i=0; i<N-1; i++) {
102 for (var j=i+1; j<N; j++) {
103 var a = balls[i].r+balls[j].r;
104 var r2 = (balls[i].x-balls[j].x)*(balls[i].x-balls[j].x)+(balls[i].y-balls[j].y)*(balls[i].y-balls[j].y);
105 var Fx = 12*D/a/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].x-balls[j].x);
106 var Fy = 12*D/a/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].y-balls[j].y);
107 balls[i].Fx += Fx/balls[i].m;
108 balls[i].Fy += Fy/balls[i].m;
109 balls[j].Fx -= Fx/balls[j].m;
110 balls[j].Fy -= Fy/balls[j].m;
111 }
112 var a = balls[i].r+r_ball.r;
113 var r2 = (balls[i].x-r_ball.x)*(balls[i].x-r_ball.x)+(balls[i].y-r_ball.y)*(balls[i].y-r_ball.y);
114 if (r2<a*a) {
115 var Fx = 12*D/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].x-r_ball.x);
116 var Fy = 12*D/a*(Math.pow(a, 14)/Math.pow(r2, 7)-Math.pow(a, 8)/Math.pow(r2, 4))*(balls[i].y-r_ball.y);
117 balls[i].Fx += Fx/balls[i].m;
118 balls[i].Fy += Fy/balls[i].m;
119 r_ball.Fx -= Fx/r_ball.m;
120 r_ball.Fy -= Fy/r_ball.m;
121 }
122 }
123
124 // двигаем шарики
125 for (var i=0; i<N; i++) {
126 balls[i].vx += balls[i].Fx*dt;
127 balls[i].vy += (balls[i].Fy+g)*dt;
128 balls[i].x += balls[i].vx*dt;
129 balls[i].y += balls[i].vy*dt;
130
131 if (balls[i].y < r) {
132 balls[i].y = r;
133 }
134
135 if (balls[i].y > h-r) {
136 balls[i].y = h-r;
137 }
138
139 if (balls[i].x>w-r) {
140 balls[i].x = w-r;
141 }
142
143 if (balls[i].x<r) {
144 balls[i].x = r;
145 }
146 var betta = 0.7;
147 r_ball.vx += (r_ball.Fx-betta*r_ball.vx)*dt;
148 r_ball.vy += (r_ball.Fy+g-betta*r_ball.vy)*dt;
149 r_ball.x += r_ball.vx*dt;
150 r_ball.y += r_ball.vy*dt;
151
152 if (r_ball.y < r) {
153 r_ball.vy *=-1;
154 }
155
156 if (r_ball.y > h-20) {
157 r_ball.vy *=-1;
158 }
159
160 if (r_ball.x>w-20) {
161 r_ball.vx *=-1;
162 }
163
164 if (r_ball.x<20) {
165 r_ball.vx *=-1;
166 }
167 }
168 }
169
170
171 draw();
172
173 function control() {
174 phys();
175 draw();
176 }
177
178 var timer = setInterval(control, 10);
179 }
180 }