КП: Молекула углекислого газа
Курсовой проект по Теоретической механике
Исполнитель: Смирнов Александр
Группа: 09 (23604)
Семестр: весна 2015
Содержание
Аннотация проекта
Моделирование молекул, даже самых простых - сложная задача. Для их моделирования необходимо использовать многочастичные потенциалы, но их поограммирование - тоже очень сложная задача. Встает вопрос о том, можло ли найти более простой путь моделирования простейших молекул.
Для моделирования хорошо подходят парные потенциалы, ибо они имеют простой вид и легко программируются. Но как их применить к моделирования молекул ? Моя работа и посвещена решению данной проблемы.
Формулировка задачи
Смоделировать с помощью многочастичного потенциала молекулу углекислого газа ( 2D модель ) и рассмотреть ее простейшую динамику частицы.
Общие сведения по теме
Для решения задачи будем использовать два потенциала: потенциал Морзе и потенциал Леннард-Джонса.
Потенциал Морзе
Парный силовой потенциал взаимодействия. Определяется формулой:
где
- — энергия связи,
- — длина связи,
- — параметр, характеризующий ширину потенциальной ямы.
Потенциал имеет один безразмерный параметр
. При взаимодействия Морзе и Леннард-Джонса близки. При увеличении ширина потенциальной ямы для взаимодействия Морзе уменьшается, взаимодействие становится более жестким и хрупким. Уменьшение приводит к противоположным изменениям — потенциальная яма расширяется, жесткость падает. Сила, соответствующая потенциалу Морзе, вычисляется по формуле:Или в векторной форме:
Потенциал Леннард-Джонса
Также парный силовой потенциал взаимодействия. Определяется формулой:
где
- — расстояние между частицами,
- — энергия связи,
- — длина связи.
Сила взаимодействия, соответствующая потенциалу Леннард-Джонса, вычисляется по формуле
Векторная сила взаимодействия определяется формулой
Углекислый газ
Углекислый газ ( диоксид углерода ) - газ без запаха и цвета. Молекула углекислого газа имеет линейное строение и ковалентные полярные связи, хотя сама молекула не является полярной. Дипольный момент = 0.
Решение
Взяв за основу программу Balls v4, было получено:
- программа, в которой можно рассмотреть динамику одной молекулы углекислого газа в другом газе ( например в азоте ).
- 2 версии программы с различными потенциалами.
- создание молекулы за конечное время.
Первая версия (потенциал Морзе)
- Синий шар - кислород .
- Коралловый шар - углерод .
- Желтый шар - азот.
Вторая версия (потенциал Морзе)
- Цвет шаров аналогичный.
- Левая кнопка мыши - добавление желтой частицы.
- Правая кнопка мыши - удаление любого шара.
- В системе теперь присутствует несколько молекул.
Файл CO2.js
1 // m: Вязкоупругий шар
2 // Версия 4.5 от 05.11.2014
3
4 window.addEventListener("load", MainBalls, true);
5 function MainBalls() {
6
7 // Предварительные установки
8
9 var canvas = canvasBalls;
10 var context = canvas.getContext("2d"); // на context происходит рисование
11 canvas.oncontextmenu = function (e) {return false;}; // блокировка контекстного меню
12
13 var Pi = 3.1415926; // число "пи"
14
15 var m0 = 1; // масштаб массы
16 var T0 = 1; // масштаб времени (период колебаний исходной системы)
17 var a0 = 1; // масштаб расстояния (диаметр шара)
18
19 var g0 = a0 / T0 / T0; // масштаб ускорения (ускорение, при котором за T0 будет пройдено расстояние a0)
20 var k0 = 2 * Pi / T0; // масштаб частоты
21 var C0 = m0 * k0 * k0; // масштаб жесткости
22 var B0 = 2 * m0 * k0; // масштаб вязкости
23
24 // *** Задание физических параметров ***
25
26 var Ny = 5; // число шаров, помещающихся по вертикали в окно (задает размер шара относительно размера окна)
27 var m = 1 * m0; // масса
28 var Cwall = 10 * C0; // жесткость стен
29 var B = 0.003 * B0; // вязкость среды
30 var Bwall = 0.03 * B0; // вязкость на стенках
31 var Cball = 0.1 * Cwall; // жесткость между частицами
32 var mg = 0//0.25 * m * g0; // сила тяжести
33 var r = 0.1 * a0; // радиус частицы в расчетных координатах
34 var K = 0.85; // сила взаимодействия ограничивается значением, реализующимся при r/a = K
35 var a = 5 * r; // равновесное расстояние между частицами
36 var a_1 = 2.1 * r;
37 var a_2 = 2.1 * a ;
38 var aCut = 2 * r ; // радиус обрезания
39 var alfa = 5 ;
40
41
42 // *** Задание вычислительных параметров ***
43
44 var fps = 50; // frames per second - число кадров в секунду (качечтво отображения)
45 var spf = 100; // steps per frame - число шагов интегрирования между кадрами (скорость расчета)
46 var dt = 0.045 * T0 / fps; // шаг интегрирования (качество расчета)
47
48 // Выполнение программы
49
50 var scale = canvas.height / Ny / a0 ; // масштабный коэффициент для перехода от расчетных к экранным координатам
51 var r2 = r * r ; // ___в целях оптимизации___
52 var aCut2 = aCut * aCut ; // ___в целях оптимизации___
53 var a2 = a * a ; // ___в целях оптимизации___
54 var a22 = a_2 * a_2 ;
55 var a11 = a_1 * a_1 ;
56 var D = a2 * Cball / 72 ; // энергия связи между частицами
57 var LJCoeff = 12 * D / a2 ; // коэффициент для расчета потенциала Л-Дж
58 var a1 = alfa / a ;
59 var MorzCoeff = 2 * a1 * D ;
60
61 var Ka = K * r ; // ___в целях оптимизации___
62 var K2a2 = Ka*Ka ; // ___в целях оптимизации___
63
64 var w = canvas.width / scale ; // ширина окна в расчетных координатах
65 var h = canvas.height / scale ; // высота окна в расчетных координатах
66
67
68
69
70
71 var dNd = null ; // ссылка на захваченный курсором шар (drag & drop)
72
73 // Работа с мышью
74
75 var mx_, my_; // буфер позиции мыши (для расчета скорости при отпускании шара)
76
77 canvas.onmousedown = function(e) { // функция при нажатии клавиши мыши
78 var m = mouseCoords(e); // получаем расчетные координаты курсора мыши
79 // цикл в обратную сторону, чтобы захватывать шар, нарисованный "сверху"
80 // (т.к. цикл рисования идет в обычном порядке)
81 for (var i = balls.length - 1; i >= 0; i--) {
82 var b = balls[i];
83 var rx = b.x - m.x;
84 var ry = b.y - m.y;
85 var rLen2 = rx * rx + ry * ry; // квадрат расстояния между курсором и центром шара
86 if (rLen2 <= r2) { // курсор нажал на шар
87 if (e.which == 1) { // нажата левая клавиша мыши
88 dNd = b;
89 dNd.xPlus = dNd.x - m.x; // сдвиг курсора относительно центра шара по x
90 dNd.yPlus = dNd.y - m.y; // сдвиг курсора относительно центра шара по y
91 mx_ = m.x; my_ = m.y;
92 canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
93 } else if (e.which == 3) { // нажата правая клавиша мыши
94 balls.splice(i, 1); // удалить шар
95 }
96 return;
97 }
98 }
99 for (var i = C.length - 1; i >= 0; i--) {
100 var b = C[i];
101 var rx = b.x - m.x;
102 var ry = b.y - m.y;
103 var rLen2 = rx * rx + ry * ry; // квадрат расстояния между курсором и центром шара
104 if (rLen2 <= r2) { // курсор нажал на шар
105 if (e.which == 1) { // нажата левая клавиша мыши
106 dNd = b;
107 dNd.xPlus = dNd.x - m.x; // сдвиг курсора относительно центра шара по x
108 dNd.yPlus = dNd.y - m.y; // сдвиг курсора относительно центра шара по y
109 mx_ = m.x; my_ = m.y;
110 canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
111 } else if (e.which == 3) { // нажата правая клавиша мыши
112 C.splice(i, 1); // удалить шар
113 }
114 return;
115 }
116 }
117 for (var i = O1.length - 1; i >= 0; i--) {
118 var b = O1[i];
119 var rx = b.x - m.x;
120 var ry = b.y - m.y;
121 var rLen2 = rx * rx + ry * ry; // квадрат расстояния между курсором и центром шара
122 if (rLen2 <= r2) { // курсор нажал на шар
123 if (e.which == 1) { // нажата левая клавиша мыши
124 dNd = b;
125 dNd.xPlus = dNd.x - m.x; // сдвиг курсора относительно центра шара по x
126 dNd.yPlus = dNd.y - m.y; // сдвиг курсора относительно центра шара по y
127 mx_ = m.x; my_ = m.y;
128 canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
129 } else if (e.which == 3) { // нажата правая клавиша мыши
130 O1.splice(i, 1); // удалить шар
131 }
132 return;
133 }
134 }
135 for (var i = O2.length - 1; i >= 0; i--) {
136 var b = O2[i];
137 var rx = b.x - m.x;
138 var ry = b.y - m.y;
139 var rLen2 = rx * rx + ry * ry; // квадрат расстояния между курсором и центром шара
140 if (rLen2 <= r2) { // курсор нажал на шар
141 if (e.which == 1) { // нажата левая клавиша мыши
142 dNd = b;
143 dNd.xPlus = dNd.x - m.x; // сдвиг курсора относительно центра шара по x
144 dNd.yPlus = dNd.y - m.y; // сдвиг курсора относительно центра шара по y
145 mx_ = m.x; my_ = m.y;
146 canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
147 } else if (e.which == 3) { // нажата правая клавиша мыши
148 O2.splice(i, 1); // удалить шар
149 }
150 return;
151 }
152 }
153
154 // если не вышли по return из цикла - нажатие было вне шара, добавляем новый
155 if (e.which == 1) {
156 dNd = addNewBall(m.x, m.y); // добавляем шар и сразу захватываем его курсором
157 if (dNd == null) return; // если шар не добавился (из за стен или других шаров) - возвращаемся
158 dNd.xPlus = 0; dNd.yPlus = 0; // держим шар по центру
159 mx_ = m.x; my_ = m.y;
160 canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
161 }
162
163
164 };
165
166 document.onmouseup = function(e) { // функция при отпускании клавиши мыши
167 canvas.onmousemove = null; // когда клавиша отпущена - функции перемещения нету
168 dNd = null; // когда клавиша отпущена - захваченного курсором шара нету
169 };
170
171 function mouseMove(e) { // функция при перемещении мыши, работает только с зажатой ЛКМ
172 var m = mouseCoords(e); // получаем расчетные координаты курсора мыши
173 dNd.x = m.x + dNd.xPlus;
174 dNd.y = m.y + dNd.yPlus;
175 dNd.vx = 0.6 * (m.x - mx_) / dt / fps; dNd.vy = 0.6 * (m.y - my_) / dt / fps;
176 mx_ = m.x; my_ = m.y;
177 }
178
179 function mouseCoords(e) { // функция возвращает расчетные координаты курсора мыши
180 var m = [];
181 var rect = canvas.getBoundingClientRect();
182 m.x = (e.clientX - rect.left) / scale;
183 m.y = (e.clientY - rect.top) / scale;
184 return m;
185 }
186
187 // Работа с массивом
188
189 var balls = []; // массив шаров
190 var C =[] ;
191 var O1 = [] ;
192 var O2 = [] ;
193
194 var addNewBall = function(x, y) {
195 // проверка - не пересекается ли новый шар со стенами или уже существующими шарами
196 if (x - r < 0 || x + r > w || y - r < 0 || y + r > h) return null;
197 for (var i = 0; i < balls.length; i++) {
198 var rx = balls[i].x - x;
199 var ry = balls[i].y - y;
200 var rLen2 = rx * rx + ry * ry;
201 if (rLen2 < 4 * r2) return null;
202 }
203 var b = [];
204
205 b.x = x; b.y = y; // расчетные координаты шара
206 b.fx = 0; b.fy = mg; // сила, действующая на шар
207 b.vx = 0; b.vy = 0; // скорость
208
209 balls[balls.length] = b; // добавить элемент в конец массива
210
211 return b;
212 };
213
214 var addNewC = function(x, y) {
215 // проверка - не пересекается ли новый шар со стенами или уже существующими шарами
216 if (x - r < 0 || x + r > w || y - r < 0 || y + r > h) return null;
217 for (var i = 0; i < balls.length; i++) {
218 var rx = balls[i].x - x;
219 var ry = balls[i].y - y;
220 var rLen2 = rx * rx + ry * ry;
221 if (rLen2 < 4 * r2) return null;
222 }
223 var b = [];
224
225 b.x = x; b.y = y; // расчетные координаты шара
226 b.fx = 0; b.fy = mg; // сила, действующая на шар
227 b.vx = 0; b.vy = 0; // скорость
228
229 C[C.length] = b; // добавить элемент в конец массива
230
231 return b;
232 };
233
234 var addNewO1 = function(x, y) {
235 // проверка - не пересекается ли новый шар со стенами или уже существующими шарами
236 if (x - r < 0 || x + r > w || y - r < 0 || y + r > h) return null;
237 for (var i = 0; i < balls.length; i++) {
238 var rx = balls[i].x - x;
239 var ry = balls[i].y - y;
240 var rLen2 = rx * rx + ry * ry;
241 if (rLen2 < 4 * r2) return null;
242 }
243 var b = [];
244
245 b.x = x; b.y = y; // расчетные координаты шара
246 b.fx = 0; b.fy = mg; // сила, действующая на шар
247 b.vx = 0; b.vy = 0; // скорость
248
249 O1[O1.length] = b; // добавить элемент в конец массива
250
251 return b;
252 };
253
254 var addNewO2 = function(x, y) {
255 // проверка - не пересекается ли новый шар со стенами или уже существующими шарами
256 if (x - r < 0 || x + r > w || y - r < 0 || y + r > h) return null;
257 for (var i = 0; i < balls.length; i++) {
258 var rx = balls[i].x - x;
259 var ry = balls[i].y - y;
260 var rLen2 = rx * rx + ry * ry;
261 if (rLen2 < 4 * r2) return null;
262 }
263 var b = [];
264
265 b.x = x; b.y = y; // расчетные координаты шара
266 b.fx = 0; b.fy = mg; // сила, действующая на шар
267 b.vx = 0; b.vy = 0; // скорость
268
269 O2[O2.length] = b; // добавить элемент в конец массива
270
271 return b;
272 };
273
274 // Основной цикл программы
275
276 function control() {
277 physics();
278 draw();
279 }
280
281 // Расчетная часть программы
282
283 function powers(b ,b2 , hkk , jk ) {
284 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
285 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
286
287 var rLen = (Math.sqrt(r2));
288
289 if (r2 < K2a2) {
290 if (rLen > 0.00001) { // проверка, чтобы избежать деления на 0
291 rx = rx / rLen * Ka;
292 ry = ry / rLen * Ka;
293 }
294 r2 = K2a2;
295 rLen = Ka; // корень K2a2
296 }
297
298 // сила взаимодействия
299
300 var u = Math.exp( -a1 * ( rLen - hkk )) ;
301 var F = jk * MorzCoeff * u* ( u - 1 ) /rLen ;
302
303 var Fx = F * rx; var Fy = F * ry;
304 b.fx += Fx; b.fy += Fy;
305 b2.fx -= Fx; b2.fy -= Fy;
306 }
307
308
309 function physics() { // то, что происходит каждый шаг времени
310 for (var s = 1; s <= spf; s++) {
311
312 // пересчет сил идет отдельным массивом, т.к. далее будут добавляться силы взаимодействия между шарами
313
314 for (var i0 = 0; i0 < balls.length; i0++) {
315 balls[i0].fx = - B * balls[i0].vx;
316 balls[i0].fy = mg - B * balls[i0].vy;
317 }
318 for (var i0 = 0; i0 < C.length; i0++) {
319 C[i0].fx = - B * C[i0].vx;
320 C[i0].fy = mg - B * C[i0].vy;
321 }
322 for (var i0 = 0; i0 < O1.length; i0++) {
323 O1[i0].fx = - B * O1[i0].vx;
324 O1[i0].fy = mg - B * O1[i0].vy;
325 }
326 for (var i0 = 0; i0 < O2.length; i0++) {
327 O2[i0].fx = - B * O2[i0].vx;
328 O2[i0].fy = mg - B * O2[i0].vy;
329 }
330
331
332 for (var i = 0; i < balls.length; i++) { // dlya Balls
333 // расчет взаимодействия производится со всеми следующими шарами в массиве,
334 // чтобы не считать каждое взаимодействие дважды
335
336 var b = balls[i];
337
338 for (var j = i + 1; j < balls.length; j++) {
339 var b2 = balls[j];
340 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
341 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
342
343 if ( r2 > aCut2 ) continue ;
344
345 powers(b,b2,a_1,0.3) ;
346
347 }
348 for (var j = 0; j < C.length; j++) {
349 var b2 = C[j];
350 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
351 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
352
353 if ( r2 > aCut2 ) continue ;
354
355 powers(b,b2,a_1,0.3) ;
356
357 }
358 for (var j = 0; j < O1.length; j++) {
359 var b2 = O1[j];
360 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
361 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
362
363 if ( r2 > aCut2 ) continue ;
364
365 powers(b,b2,a_1,0.3) ;
366
367 }
368
369 for (var j = 0; j < O2.length; j++) {
370 var b2 = O2[j];
371 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
372 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
373
374 if ( r2 > aCut2 ) continue ;
375
376 powers( b, b2, a_1 ,0.3) ;
377
378 }
379
380 if (b == dNd) continue; // если шар схвачен курсором - его вз. со стенами и перемещение не считаем
381
382 if (b.y + r > h) { b.fy += -Cwall * (b.y + r - h) - Bwall * b.vy; }
383 if (b.y - r < 0) { b.fy += -Cwall * (b.y - r) - Bwall * b.vy;}
384 if (b.x + r > w) { b.fx += -Cwall * (b.x + r - w) - Bwall * b.vx; }
385 if (b.x - r < 0) { b.fx += -Cwall * (b.x - r) - Bwall * b.vx; }
386
387 b.vx += b.fx / m * dt; b.vy += b.fy / m * dt;
388 b.x += b.vx * dt; b.y += b.vy * dt;
389
390 }
391
392 for (var i = 0; i < C.length; i++) { // dlya C
393 // расчет взаимодействия производится со всеми следующими шарами в массиве,
394 // чтобы не считать каждое взаимодействие дважды
395
396 var b = C[i];
397
398 for (var j = i + 1; j < C.length; j++) {
399 var b2 = C[j];
400 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
401 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
402
403 if ( r2 > aCut2 ) continue ;
404
405 powers(b,b2,a_1, 0.3) ;
406
407 }
408 for (var j = 0; j < O1.length; j++) {
409 var b2 = O1[j];
410 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
411 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
412
413 if ( j == i ) { powers(b,b2,a, 6) ;}
414 else {
415 if ( r2 > aCut2 ) continue ;
416 powers(b,b2,a_1, 0.3) ;
417 }
418
419 }
420
421 for (var j = 0; j < O2.length; j++) {
422 var b2 = O2[j];
423 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
424 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
425
426 if ( j == i ) { powers(b,b2,a,6) ;}
427 else {
428 if ( r2 > aCut2 ) continue ;
429 powers(b,b2,a_1, 0.3) ;
430 }
431
432 }
433
434 if (b == dNd) continue; // если шар схвачен курсором - его вз. со стенами и перемещение не считаем
435
436 if (b.y + r > h) { b.fy += -Cwall * (b.y + r - h) - Bwall * b.vy; }
437 if (b.y - r < 0) { b.fy += -Cwall * (b.y - r) - Bwall * b.vy;}
438 if (b.x + r > w) { b.fx += -Cwall * (b.x + r - w) - Bwall * b.vx; }
439 if (b.x - r < 0) { b.fx += -Cwall * (b.x - r) - Bwall * b.vx; }
440
441 b.vx += b.fx / m * dt; b.vy += b.fy / m * dt;
442 b.x += b.vx * dt; b.y += b.vy * dt;
443
444 }
445
446 for (var i = 0; i < C.length; i++) { // dlya O1
447 // расчет взаимодействия производится со всеми следующими шарами в массиве,
448 // чтобы не считать каждое взаимодействие дважды
449
450 var b = O1[i];
451
452 for (var j = i + 1; j < O1.length; j++) {
453
454 var b2 = O1[j];
455 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
456 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
457
458 if ( r2 > aCut2 ) continue ;
459
460 powers(b,b2,a_1,0.3) ;
461
462 }
463
464 for (var j = 0; j < O2.length; j++) {
465 var b2 = O2[j];
466 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
467 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
468
469 if ( i == j ) { powers(b,b2,a_2, 3) ;}
470 else {
471 if ( r2 > aCut2 ) continue ;
472 else powers(b,b2,a_1 , 0.3) ;
473 }
474
475 }
476
477 if (b == dNd) continue; // если шар схвачен курсором - его вз. со стенами и перемещение не считаем
478
479 if (b.y + r > h) { b.fy += -Cwall * (b.y + r - h) - Bwall * b.vy; }
480 if (b.y - r < 0) { b.fy += -Cwall * (b.y - r) - Bwall * b.vy;}
481 if (b.x + r > w) { b.fx += -Cwall * (b.x + r - w) - Bwall * b.vx; }
482 if (b.x - r < 0) { b.fx += -Cwall * (b.x - r) - Bwall * b.vx; }
483
484 b.vx += b.fx / m * dt; b.vy += b.fy / m * dt;
485 b.x += b.vx * dt; b.y += b.vy * dt;
486
487 }
488
489 for (var i = 0; i < C.length; i++) { // dlya O2
490 // расчет взаимодействия производится со всеми следующими шарами в массиве,
491 // чтобы не считать каждое взаимодействие дважды
492
493 var b = O2[i];
494
495 for (var j = i + 1; j < O2.length; j++) {
496 var b2 = O2[j];
497 var rx = b.x - b2.x; var ry = b.y - b2.y; // вектор смотрит на первый шар (b)
498 var r2 = rx * rx + ry * ry; // квадрат расстояния между шарами
499
500 if ( r2 > aCut2) continue ;
501
502 powers(b,b2,a_1, 0.3) ;
503
504 }
505
506 if (b == dNd) continue; // если шар схвачен курсором - его вз. со стенами и перемещение не считаем
507
508 if (b.y + r > h) { b.fy += -Cwall * (b.y + r - h) - Bwall * b.vy; }
509 if (b.y - r < 0) { b.fy += -Cwall * (b.y - r) - Bwall * b.vy;}
510 if (b.x + r > w) { b.fx += -Cwall * (b.x + r - w) - Bwall * b.vx; }
511 if (b.x - r < 0) { b.fx += -Cwall * (b.x - r) - Bwall * b.vx; }
512
513 b.vx += b.fx / m * dt; b.vy += b.fy / m * dt;
514 b.x += b.vx * dt; b.y += b.vy * dt;
515
516 }
517 }
518 }
519
520 // Рисование
521
522 var rScale13 = r * scale * 1.3; // ___в целях оптимизации___
523 var rScaleShift = r * scale / 5; // ___в целях оптимизации___
524 function draw() {
525 context.clearRect(0, 0, w * scale, h * scale); // очистить экран
526 for (var i = 0; i < balls.length; i++){
527 var xS = balls[i].x * scale; var yS = balls[i].y * scale;
528
529 context.fillStyle = "#FFD700";
530
531 context.beginPath();
532 context.arc(xS, yS, r * scale, 0, 2 * Math.PI, false);
533 context.closePath();
534 context.fill();
535 }
536
537 for (var i = 0; i < C.length; i++){
538 var xS = C[i].x * scale; var yS = C[i].y * scale;
539
540 context.fillStyle = "#f08080";
541
542 context.beginPath();
543 context.arc(xS, yS, r * scale, 0, 2 * Math.PI, false);
544 context.closePath();
545 context.fill();
546 }
547 for (var i = 0; i < O1.length; i++){
548 var xS = O1[i].x * scale; var yS = O1[i].y * scale;
549
550 context.fillStyle = "#3070d0";
551
552 context.beginPath();
553 context.arc(xS, yS, r * scale, 0, 2 * Math.PI, false);
554 context.closePath();
555 context.fill();
556 }
557 for (var i = 0; i < O2.length; i++){
558 var xS = O2[i].x * scale; var yS = O2[i].y * scale;
559
560 context.fillStyle = "#3070d0";
561
562 context.beginPath();
563 context.arc(xS, yS, r * scale, 0, 2 * Math.PI, false);
564 context.closePath();
565 context.fill();
566 }
567 }
568
569 // Запуск системы
570 for (var i = 0; i < 8; i++){ // добавляем 20 частиц, сдвинув их от стен
571 //addNewBall(Math.random() * (w - 2 * r) + r, Math.random() * (h - 2 * r) + r , 10 );
572 addNewC(Math.random() * (w - 2 * r) + r, Math.random() * (h - 2 * r) + r , 10 );
573 addNewO1(Math.random() * (w - 2 * r) + r, Math.random() * (h - 2 * r) + r , 10 );
574 addNewO2(Math.random() * (w - 2 * r) + r, Math.random() * (h - 2 * r) + r , 10 );
575
576 }
577 setInterval(control, 1000 / fps);
578 }
Обсуждение результатов и выводы
Можно смоделировать молекулу с помощью парных потенциалов. За конечное время при небольшой вязкости среды частицы собираются в молекулы. При моделировании частиц только с помощью парных потенциалов молекула получается очень неустойчивой. Но ее поведение в системе при небольших скоростях получается достаточно правдаподобной. Это означает что можно изучать динамику системы при малых скоростях частиц. При больших скоростях частицы разрушаются. После разрушения они собираются заного, образуя те же самые частицы.
Скачать презентацию: Молекула углекислого газа в среде инертного газа