Молекулярная динамика — различия между версиями
Материал из Department of Theoretical and Applied Mechanics
(→Визуализация) |
Mstislav (обсуждение | вклад) (→Код программы) |
||
(не показано 8 промежуточных версий 2 участников) | |||
Строка 13: | Строка 13: | ||
== Визуализация == | == Визуализация == | ||
− | {{#widget:Iframe | url= http://tm.spbstu.ru/htmlets/js2020/Litvinova/particleshtml.html |width=600 | height= | + | {{#widget:Iframe | url= http://tm.spbstu.ru/htmlets/js2020/Litvinova/particleshtml.html |width=600 | height=1250| border=0}} |
==Код программы== | ==Код программы== | ||
+ | Код программы: | ||
+ | <div class="mw-collapsible mw-collapsed"> | ||
+ | '''JS:''' <div class="mw-collapsible-content"> | ||
+ | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
+ | <br /> | ||
+ | window.addEventListener('load',main,false) | ||
+ | function main(){ | ||
+ | var N = document.getElementById("num").value; | ||
+ | Num = document.getElementById("num").value; | ||
+ | my = document.getElementById("my"); | ||
+ | my.innerHTML =Num + " частиц"; | ||
+ | var animation = 0; | ||
+ | var za = 0; | ||
+ | var ctx2 = canvasex2.getContext('2d'); | ||
+ | var cplot = canvasex1.getContext('2d'); | ||
+ | var cpl = canvasex3.getContext('2d'); | ||
+ | var w = canvasex1.width; | ||
+ | var h = canvasex1.height; | ||
+ | var particles = []; | ||
+ | var t_max = 0; | ||
+ | var E=[]; | ||
+ | var Ep=[]; | ||
+ | una.onclick= function una(){ | ||
+ | animation = 0; | ||
+ | } | ||
+ | start.onclick= function start(){ | ||
+ | var D = document.getElementById("D").value; //энергия связи | ||
+ | var beta = document.getElementById("b").value; //вязкость | ||
+ | animation=1; | ||
+ | za += 1; | ||
+ | var l = canvasex2.height; | ||
+ | var a = 30; //равновесное расстояние | ||
+ | var m = 1; | ||
+ | var rad = 10; | ||
+ | var dt=1/60; | ||
+ | |||
+ | function Particle(x,y,vx,vy){ | ||
+ | var that=this; | ||
+ | this.x=x; | ||
+ | this.y=y; | ||
+ | this.vx=vx; | ||
+ | this.vy=vy; | ||
+ | this.info = function (){ | ||
+ | console.log('Position: ('+that.x+','+that.y+')\nVelocity: ('+that.vx+','+that.vy+')') | ||
+ | } | ||
+ | this.move=function(){ | ||
+ | if ((that.x-rad)<0||(that.x+rad)>l){ | ||
+ | that.vx*=-1; | ||
+ | } | ||
+ | if ((that.y-rad)<0||(that.y+rad)>l){ | ||
+ | that.vy*=-1; | ||
+ | } | ||
+ | that.x+=that.vx*dt; | ||
+ | that.y+=that.vy*dt; | ||
+ | } | ||
+ | this.draw = function(){ | ||
+ | ctx2.beginPath(); | ||
+ | ctx2.arc(that.x,that.y,rad,0,2*Math.PI); | ||
+ | ctx2.fillStyle = '#9999FF'; | ||
+ | ctx2.fill(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | if (za==1){ // создание частиц | ||
+ | for(var i=0;i<N;i++){ | ||
+ | var fi= Math.random()*2*Math.PI; | ||
+ | particles.push( | ||
+ | new Particle( | ||
+ | 50+Math.random()*400, | ||
+ | 50+Math.random()*400, | ||
+ | 20*Math.cos(fi), | ||
+ | 20*Math.sin(fi), | ||
+ | ) | ||
+ | ); | ||
+ | if (i!=0){ | ||
+ | for (var z = 1;i-z>=0;z++) | ||
+ | { | ||
+ | if (Math.sqrt((particles[i].x-particles[i-z].x)*(particles[i].x-particles[i-z].x)+(particles[i].y-particles[i-z].y)*(particles[i].y-particles[i-z].y))<a) | ||
+ | { particles.length = particles.length-1; | ||
+ | i = i-1; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | particles[i].draw(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function phys(){ | ||
+ | var ep = 0; | ||
+ | for(var i=0;i<N;i++){ | ||
+ | particles[i].move(); | ||
+ | for(var j=0;j<N;j++){; | ||
+ | if(i!=j){ | ||
+ | var F = 0; | ||
+ | var rx = particles[j].x-particles[i].x; | ||
+ | var ry = particles[j].y-particles[i].y; | ||
+ | var r = Math.sqrt(Math.pow(rx,2)+Math.pow(ry,2)); | ||
+ | var K = Math.pow(1-Math.pow((r*r-1.21*a*a)/(16-1.21)/a/a,2),2); | ||
+ | if (r<1.1*a){ K = 1; } | ||
+ | if (r>4*a){ K = 0; } | ||
+ | if (r<15){ r = 15; } | ||
+ | F = K*(12*D/a)*(Math.pow((a/r),13)-Math.pow((a/r),7)); | ||
+ | ep+=D*(Math.pow((a/r),12)-2*Math.pow((a/r),6)); | ||
+ | particles[i].vx = (particles[i].vx*Math.exp(-beta*dt) - (rx/r)*F*dt/m); | ||
+ | particles[i].vy = (particles[i].vy*Math.exp(-beta*dt) - (ry/r)*F*dt/m); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | for (var i=0;i<N;i++){ | ||
+ | particles[i].x = particles[i].x+particles[i].vx*dt; | ||
+ | particles[i].y = particles[i].y+particles[i].vy*dt; | ||
+ | } | ||
+ | Ep.push(ep); | ||
+ | var e = 0; | ||
+ | for (var ii=0;ii<N;ii++){ | ||
+ | e+=(particles[ii].vx*particles[ii].vx+particles[ii].vy*particles[ii].vy)/2; | ||
+ | } | ||
+ | E.push(e); | ||
+ | t_max+=dt; | ||
+ | } | ||
+ | |||
+ | function draw(){ | ||
+ | ctx2.clearRect(0,0,500,500); | ||
+ | for(var i=0;i<N;i++){ | ||
+ | particles[i].draw();} | ||
+ | var Ep_scale =(h-20)/Math.max.apply(null,Ep); | ||
+ | var E_scale =(h-20)/Math.max.apply(null,E); | ||
+ | var t_scale= w/t_max; | ||
+ | cplot.beginPath(); | ||
+ | cpl.beginPath(); | ||
+ | for (var i =0; i<E.length-1; i++){ | ||
+ | cplot.clearRect(0,0,w,h); | ||
+ | cpl.clearRect(0,0,w,h); | ||
+ | cplot.moveTo(dt*i*t_scale,3*h/4-Ep[i]*(Ep_scale)); | ||
+ | cplot.lineTo(dt*(i+1)*t_scale, 3*h/4-Ep[i+1]*(Ep_scale)); | ||
+ | cplot.font = "28px calibri"; | ||
+ | cplot.strokeText("Ep="+Ep[i].toFixed(1),20,280) | ||
+ | cpl.moveTo(dt*i*t_scale,h-E[i]*(E_scale)); | ||
+ | cpl.lineTo(dt*(i+1)*t_scale, h-E[i+1]*(E_scale)); | ||
+ | cpl.font = "28px calibri"; | ||
+ | cpl.strokeText("Ek="+E[i].toFixed(1),20,280) | ||
+ | cplot.stroke(); | ||
+ | cpl.stroke(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function control(){ | ||
+ | if (animation!=0){ | ||
+ | phys(); | ||
+ | draw(); | ||
+ | } | ||
+ | } | ||
+ | setInterval(control,1000*dt); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | </div> | ||
+ | <div class="mw-collapsible mw-collapsed"> | ||
+ | '''HTML:''' <div class="mw-collapsible-content"> | ||
+ | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
+ | <!DOCTYPE html> | ||
+ | <html> | ||
+ | <head> | ||
+ | <title>Particles</title> | ||
+ | <script src='particles.js'></script> | ||
+ | <style> | ||
+ | input{ | ||
+ | width:100px; | ||
+ | height:30px; | ||
+ | } | ||
+ | button{ | ||
+ | width:90px; | ||
+ | height:30px; | ||
+ | } | ||
+ | div table{ | ||
+ | margin-left:auto; | ||
+ | margin-right:auto;} | ||
+ | table td{ | ||
+ | text-align:center; | ||
+ | width:180px; | ||
+ | height:30px; | ||
+ | } | ||
+ | </style> | ||
+ | </head> | ||
+ | <body> | ||
+ | <center> | ||
+ | <h1><i> Молекулярная динамика </i></h1> | ||
+ | <table> | ||
+ | <tr><td colspan="2"> | ||
+ | <canvas id='canvasex2' width=500 height=500 background-color=#FF99CC style='border: 1px dashed #000000' ></canvas> | ||
+ | </td></tr><tr><td> | ||
+ | <canvas id='canvasex1' width=220 height=300 background-color=#FF99CC style='border: 1px dashed #000000' ></canvas> | ||
+ | </td><td> | ||
+ | <canvas id='canvasex3' width=220 height=300 background-color=#FF99CC style='border: 1px dashed #000000' ></canvas> | ||
+ | </td></tr><tr> | ||
+ | <td><h2><i> Потенциальная энергия</i></td> | ||
+ | <td><h2><i> Кинетическая энергия</i> </td></tr> | ||
+ | </table> | ||
+ | <table> | ||
+ | <tr> | ||
+ | <td><input type="button" id="start" value="start" > </td> | ||
+ | <td> <input type="button" id="una" value="stop" width=40 height=20></td> | ||
+ | <td> <button onclick='window.location.reload(true)' style ='width=100 height=20'>clear</button></td> | ||
+ | </table> | ||
+ | <table> | ||
+ | <tr><th> | ||
+ | <input type="range" min="15" max="40" id="num" | ||
+ | oninput="main()" value="0"></th> | ||
+ | <th><div id="my">0</div></th></tr> | ||
+ | <tr><th> | ||
+ | <input type="number" id="b" name="b" value="0.0001" | ||
+ | min="0.0001" max="0.002" step="0.0002" style='border: 1px dashed #000000'></th> | ||
+ | <th> <div> <h3><i> Вязкость</i></div></th></tr> | ||
+ | <tr><th> | ||
+ | <input type="number" id="D" name="D" value="5" | ||
+ | min="1" max="10" step="1" style='border: 1px dashed #000000'></th> | ||
+ | <th> <div> <h3><i> Энергия связи</i></div></th></tr> | ||
+ | </table> | ||
+ | </center> | ||
+ | </body> | ||
+ | </html> | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | </div> |
Текущая версия на 14:41, 1 июня 2020
Описание[править]
Данная работа посвящена визуализации движения частиц в замкнутом объеме. Цель проекта заключается в изучении основных принципов создания рабочей модели взаимодействия. Объект исследования – процесс использования языков программирования, а также физическая теория в области динамики. Предмет исследования – программные инструменты языков JavaScript и HTML.
Исполнители :Жукин Александр,
Литвинова Ярослава
Математическая модель[править]
В данном проекте при расчете движения частиц применялась модель парного взаимодействия неполярных молекул Леннарда-Джонса, описывающая зависимость энергии взаимодействия двух частиц от расстояния между ними. Эта модель позволяет достаточно реалистично передать свойства реального взаимодействия сферических неполярных молекул.
Входные данные[править]
- Количество частиц
- Вязкость среды
- Энергия связи
Визуализация[править]
Код программы[править]
Код программы:
JS:
1 <br />
2 window.addEventListener('load',main,false)
3 function main(){
4 var N = document.getElementById("num").value;
5 Num = document.getElementById("num").value;
6 my = document.getElementById("my");
7 my.innerHTML =Num + " частиц";
8 var animation = 0;
9 var za = 0;
10 var ctx2 = canvasex2.getContext('2d');
11 var cplot = canvasex1.getContext('2d');
12 var cpl = canvasex3.getContext('2d');
13 var w = canvasex1.width;
14 var h = canvasex1.height;
15 var particles = [];
16 var t_max = 0;
17 var E=[];
18 var Ep=[];
19 una.onclick= function una(){
20 animation = 0;
21 }
22 start.onclick= function start(){
23 var D = document.getElementById("D").value; //энергия связи
24 var beta = document.getElementById("b").value; //вязкость
25 animation=1;
26 za += 1;
27 var l = canvasex2.height;
28 var a = 30; //равновесное расстояние
29 var m = 1;
30 var rad = 10;
31 var dt=1/60;
32
33 function Particle(x,y,vx,vy){
34 var that=this;
35 this.x=x;
36 this.y=y;
37 this.vx=vx;
38 this.vy=vy;
39 this.info = function (){
40 console.log('Position: ('+that.x+','+that.y+')\nVelocity: ('+that.vx+','+that.vy+')')
41 }
42 this.move=function(){
43 if ((that.x-rad)<0||(that.x+rad)>l){
44 that.vx*=-1;
45 }
46 if ((that.y-rad)<0||(that.y+rad)>l){
47 that.vy*=-1;
48 }
49 that.x+=that.vx*dt;
50 that.y+=that.vy*dt;
51 }
52 this.draw = function(){
53 ctx2.beginPath();
54 ctx2.arc(that.x,that.y,rad,0,2*Math.PI);
55 ctx2.fillStyle = '#9999FF';
56 ctx2.fill();
57 }
58 }
59
60 if (za==1){ // создание частиц
61 for(var i=0;i<N;i++){
62 var fi= Math.random()*2*Math.PI;
63 particles.push(
64 new Particle(
65 50+Math.random()*400,
66 50+Math.random()*400,
67 20*Math.cos(fi),
68 20*Math.sin(fi),
69 )
70 );
71 if (i!=0){
72 for (var z = 1;i-z>=0;z++)
73 {
74 if (Math.sqrt((particles[i].x-particles[i-z].x)*(particles[i].x-particles[i-z].x)+(particles[i].y-particles[i-z].y)*(particles[i].y-particles[i-z].y))<a)
75 { particles.length = particles.length-1;
76 i = i-1;
77 }
78 }
79 }
80 particles[i].draw();
81 }
82 }
83
84 function phys(){
85 var ep = 0;
86 for(var i=0;i<N;i++){
87 particles[i].move();
88 for(var j=0;j<N;j++){;
89 if(i!=j){
90 var F = 0;
91 var rx = particles[j].x-particles[i].x;
92 var ry = particles[j].y-particles[i].y;
93 var r = Math.sqrt(Math.pow(rx,2)+Math.pow(ry,2));
94 var K = Math.pow(1-Math.pow((r*r-1.21*a*a)/(16-1.21)/a/a,2),2);
95 if (r<1.1*a){ K = 1; }
96 if (r>4*a){ K = 0; }
97 if (r<15){ r = 15; }
98 F = K*(12*D/a)*(Math.pow((a/r),13)-Math.pow((a/r),7));
99 ep+=D*(Math.pow((a/r),12)-2*Math.pow((a/r),6));
100 particles[i].vx = (particles[i].vx*Math.exp(-beta*dt) - (rx/r)*F*dt/m);
101 particles[i].vy = (particles[i].vy*Math.exp(-beta*dt) - (ry/r)*F*dt/m);
102 }
103 }
104 }
105 for (var i=0;i<N;i++){
106 particles[i].x = particles[i].x+particles[i].vx*dt;
107 particles[i].y = particles[i].y+particles[i].vy*dt;
108 }
109 Ep.push(ep);
110 var e = 0;
111 for (var ii=0;ii<N;ii++){
112 e+=(particles[ii].vx*particles[ii].vx+particles[ii].vy*particles[ii].vy)/2;
113 }
114 E.push(e);
115 t_max+=dt;
116 }
117
118 function draw(){
119 ctx2.clearRect(0,0,500,500);
120 for(var i=0;i<N;i++){
121 particles[i].draw();}
122 var Ep_scale =(h-20)/Math.max.apply(null,Ep);
123 var E_scale =(h-20)/Math.max.apply(null,E);
124 var t_scale= w/t_max;
125 cplot.beginPath();
126 cpl.beginPath();
127 for (var i =0; i<E.length-1; i++){
128 cplot.clearRect(0,0,w,h);
129 cpl.clearRect(0,0,w,h);
130 cplot.moveTo(dt*i*t_scale,3*h/4-Ep[i]*(Ep_scale));
131 cplot.lineTo(dt*(i+1)*t_scale, 3*h/4-Ep[i+1]*(Ep_scale));
132 cplot.font = "28px calibri";
133 cplot.strokeText("Ep="+Ep[i].toFixed(1),20,280)
134 cpl.moveTo(dt*i*t_scale,h-E[i]*(E_scale));
135 cpl.lineTo(dt*(i+1)*t_scale, h-E[i+1]*(E_scale));
136 cpl.font = "28px calibri";
137 cpl.strokeText("Ek="+E[i].toFixed(1),20,280)
138 cplot.stroke();
139 cpl.stroke();
140 }
141 }
142
143 function control(){
144 if (animation!=0){
145 phys();
146 draw();
147 }
148 }
149 setInterval(control,1000*dt);
150 }
151 }
HTML:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Particles</title>
5 <script src='particles.js'></script>
6 <style>
7 input{
8 width:100px;
9 height:30px;
10 }
11 button{
12 width:90px;
13 height:30px;
14 }
15 div table{
16 margin-left:auto;
17 margin-right:auto;}
18 table td{
19 text-align:center;
20 width:180px;
21 height:30px;
22 }
23 </style>
24 </head>
25 <body>
26 <center>
27 <h1><i> Молекулярная динамика </i></h1>
28 <table>
29 <tr><td colspan="2">
30 <canvas id='canvasex2' width=500 height=500 background-color=#FF99CC style='border: 1px dashed #000000' ></canvas>
31 </td></tr><tr><td>
32 <canvas id='canvasex1' width=220 height=300 background-color=#FF99CC style='border: 1px dashed #000000' ></canvas>
33 </td><td>
34 <canvas id='canvasex3' width=220 height=300 background-color=#FF99CC style='border: 1px dashed #000000' ></canvas>
35 </td></tr><tr>
36 <td><h2><i> Потенциальная энергия</i></td>
37 <td><h2><i> Кинетическая энергия</i> </td></tr>
38 </table>
39 <table>
40 <tr>
41 <td><input type="button" id="start" value="start" > </td>
42 <td> <input type="button" id="una" value="stop" width=40 height=20></td>
43 <td> <button onclick='window.location.reload(true)' style ='width=100 height=20'>clear</button></td>
44 </table>
45 <table>
46 <tr><th>
47 <input type="range" min="15" max="40" id="num"
48 oninput="main()" value="0"></th>
49 <th><div id="my">0</div></th></tr>
50 <tr><th>
51 <input type="number" id="b" name="b" value="0.0001"
52 min="0.0001" max="0.002" step="0.0002" style='border: 1px dashed #000000'></th>
53 <th> <div> <h3><i> Вязкость</i></div></th></tr>
54 <tr><th>
55 <input type="number" id="D" name="D" value="5"
56 min="1" max="10" step="1" style='border: 1px dashed #000000'></th>
57 <th> <div> <h3><i> Энергия связи</i></div></th></tr>
58 </table>
59 </center>
60 </body>
61 </html>