Взаимодействие частиц (JavaScript) — различия между версиями
Материал из Department of Theoretical and Applied Mechanics
Строка 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 radius(){ | ||
+ | return parseFloat(R.value); | ||
+ | } | ||
+ | function svyaz(){ | ||
+ | return parseFloat(D.value); | ||
+ | } | ||
+ | |||
+ | 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:54, 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 radius(){
10 return parseFloat(R.value);
11 }
12 function svyaz(){
13 return parseFloat(D.value);
14 }
15
16 function ball(x, y, r, m, Fx, Fy) {
17 this.x = x;
18 this.y = y;
19 this.vx = 0;
20 this.vy = 0;
21 this.r = r;
22 this.m = m;
23 this.Fx = Fx;
24 this.Fy = Fy;
25 }
26
27
28
29 var X_c = w/2;
30 var Y_c = h/3;
31 var Vy_c = 0;
32
33 var balls = [];
34 var r = 10;
35
36
37 for (var i=0; i<27; i++) {
38 balls.push(new ball(r+(w)*(i/27), h-r, r, 1, 0, 0));
39 }
40 for (var i=0; i<26; i++) {
41 balls.push(new ball(2*r+(w)*(i/27), h-3*r, r, 1, 0, 0));
42 }
43 for (var i=0; i<27; i++) {
44 balls.push(new ball(r+(w)*(i/27), h-5*r, r, 1, 0, 0));
45 }
46 for (var i=0; i<26; i++) {
47 balls.push(new ball(2*r+(w)*(i/27), h-7*r, r, 1, 0, 0));
48 }
49 for (var i=0; i<27; i++) {
50 balls.push(new ball(r+(w)*(i/27), h-9*r, r, 1, 0, 0));
51 }
52 for (var i=0; i<26; i++) {
53 balls.push(new ball(2*r+(w)*(i/27), h-11*r, r, 1, 0, 0));
54 }
55 for (var i=0; i<27; i++) {
56 balls.push(new ball(r+(w)*(i/27), h-13*r, r, 1, 0, 0));
57 }
58
59 console.log(radius(R));
60 console.log(svyaz(D));
61
62 start.onclick = function() {
63 R = radius();
64 D = svyaz();
65
66
67 var r_ball = new ball(X_c, Y_c, R, 50, 0, 0)
68 r_ball.vy = 20;
69 var N = 159;
70 var a = 40;
71 var dt = 0.001;
72 var g = 1;
73
74
75
76 function draw() {
77 ctx.clearRect(0,0,w,h);
78 for (var i=0; i<N; i++) {
79 ctx.beginPath();
80 ctx.arc(balls[i].x, balls[i].y, balls[i].r, 0, 2*Math.PI);
81 ctx.fillStyle = '#FF4500'
82 ctx.stroke();
83 ctx.fill();
84
85 }
86
87
88 ctx.beginPath();
89 ctx.fillStyle = '#0000FF'
90 ctx.strokeStyle = '#000000';
91 ctx.arc(r_ball.x, r_ball.y, r_ball.r, 0, 2*Math.PI);
92 ctx.stroke();
93 ctx.fill();
94
95 }
96
97
98
99 function phys() {
100 // обнуляем силы шариков
101 for (var i=0; i<N; i++) {
102 balls[i].Fx = 0;
103 balls[i].Fy = 0;
104 }
105 r_ball.Fx = 0;
106 r_ball.Fy = 0;
107 // считаем силы
108 for (var i=0; i<N-1; i++) {
109 for (var j=i+1; j<N; j++) {
110 var a = balls[i].r+balls[j].r;
111 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);
112 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);
113 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);
114 balls[i].Fx += Fx/balls[i].m;
115 balls[i].Fy += Fy/balls[i].m;
116 balls[j].Fx -= Fx/balls[j].m;
117 balls[j].Fy -= Fy/balls[j].m;
118 }
119 var a = balls[i].r+r_ball.r;
120 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);
121 if (r2<a*a) {
122 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);
123 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);
124 balls[i].Fx += Fx/balls[i].m;
125 balls[i].Fy += Fy/balls[i].m;
126 r_ball.Fx -= Fx/r_ball.m;
127 r_ball.Fy -= Fy/r_ball.m;
128 }
129 }
130
131 // двигаем шарики
132 for (var i=0; i<N; i++) {
133 balls[i].vx += balls[i].Fx*dt;
134 balls[i].vy += (balls[i].Fy+g)*dt;
135 balls[i].x += balls[i].vx*dt;
136 balls[i].y += balls[i].vy*dt;
137
138 if (balls[i].y < r) {
139 balls[i].y = r;
140 }
141
142 if (balls[i].y > h-r) {
143 balls[i].y = h-r;
144 }
145
146 if (balls[i].x>w-r) {
147 balls[i].x = w-r;
148 }
149
150 if (balls[i].x<r) {
151 balls[i].x = r;
152 }
153 var betta = 0.7;
154 r_ball.vx += (r_ball.Fx-betta*r_ball.vx)*dt;
155 r_ball.vy += (r_ball.Fy+g-betta*r_ball.vy)*dt;
156 r_ball.x += r_ball.vx*dt;
157 r_ball.y += r_ball.vy*dt;
158
159 if (r_ball.y < r) {
160 r_ball.vy *=-1;
161 }
162
163 if (r_ball.y > h-20) {
164 r_ball.vy *=-1;
165 }
166
167 if (r_ball.x>w-20) {
168 r_ball.vx *=-1;
169 }
170
171 if (r_ball.x<20) {
172 r_ball.vx *=-1;
173 }
174 }
175 }
176
177
178 draw();
179
180 function control() {
181 phys();
182 draw();
183 }
184
185 var timer = setInterval(control, 10);
186 }
187 }