Интерактивная модель простейшей автоколебательной системы с пружиной
Материал из Department of Theoretical and Applied Mechanics
Виртуальная лаборатория > Простейшая колебательная система с двумя степенями свободы
Рассматривается простейшая колебательная система тело-пружина-конвейер. Пружина крепится к стенке. Грузик на пружинке колеблется посредством постоянной силы F, с которой тянет конвейер. Запишем уравнения движения системы :
- , где - масса грузика, - жесткость пружины, - скорость конвейера, - изменение скорости тела
Делаем замену переменных.
, где - начальная координата тела. Затем раскладываем силу в ряд Тейлора, получаем новое уравнение :Переобозначим переменные. Пусть :
Получим новое уравнение :
, где - частота колебаний.
Скачать SeregaTrouble.rar.
Текст программы на языке JavaScript (разработчик Бондарев Сергей):
Файл "2_7.js"
1 function MainParticle(canvas, canvas_gr, canvas_gr2) {
2 // Предварительные установки
3 var context = canvas.getContext("2d"); // на context происходит рисование
4 var context_gr = canvas_gr.getContext("2d"); // на context происходит рисование
5 var context_gr2 = canvas_gr2.getContext("2d");
6
7 // Задание констант
8 const Pi = 3.1415926; // число "пи"
9 const m0 = 1; // масштаб массы
10 const T0 = 1; // масштаб времени (период колебаний исходной системы)
11 const a0 = 1; // масштаб расстояния (диаметр шара)
12 const mu = 0.4; // коэф. трения
13
14
15 const g0 = a0 / T0 / T0; // масштаб ускорения (ускорение, при котором за T0 будет пройдено расстояние a0)
16 const k0 = 2 * Pi / T0; // масштаб частоты
17 const C0 = m0 * k0 * k0; // масштаб жесткости
18 var scale1 = 0.2;
19 /* var scale2 = 0.2; */
20 // *** Задание физических параметров ***
21 var xShift= 0;
22 const Ny = 15; // число шаров, помещающихся по вертикали в окно (задает размер шара относительно размера окна)
23 const Nx = 15; // число шаров, помещающихся по вертикали в окно (задает размер шара относительно размера окна)
24 const l1 = 15*a0; // длина первой пружины
25 const lmax = 2*l1; // максимальное растяжение первой пружины
26 /* const l2 = 5*a0; */ // длина второй пружины
27 var m = 5 * m0; // масса шара
28 //var v.x = 0; // скорость шара
29 var k = 1; // силовой коэффициент
30 var b1 = 0.1;
31 var b3 = 0.1;
32 var N = m*9.8; // сила трения
33 var Ftr = -mu * N ;
34 /* var m2 = 10 * m0; // масса второго шара */
35 const Cwall = 10 * C0; // жесткость стен
36 const r = 1 * a0; // радиус частицы в расчетных координатах
37 var c = 100; // "жесткость" пружинки 1
38 /* var c2 = 100; */ // "жесткость" пружинки 1
39 var vx0 = 0 * a0/T0; //начальная скорость
40 var delt = 0*a0; //начальное смещение
41 var E = 0; //энергия системы
42 var Vmax = 0; var Mmin = 0; var Vprov = 0;
43
44 var A = Math.sqrt((-4*b1*m*m)/(3*b3*c*c));
45 var Mmax= Math.max(m,10);
46 //*** Передача значений слайдерам и текстовым окнам***
47 Text_delt.value = delt;
48 Text_m.value = m;
49 Text_c.value = c;
50 Text_b1.value = b1;
51 Text_b3.value = b3;
52
53
54 Slider_b1.min = -1;
55 Slider_b1.max = 1;
56 Slider_b1.step = 0.1;
57 Slider_b1.value = Text_b1.value;
58
59 Slider_b3.min = -1;
60 Slider_b3.max = 1;
61 Slider_b3.step = 0.1;
62 Slider_b3.value = Text_b3.value;
63
64 Slider_delt.min = -5;
65 Slider_delt.max = 5;
66 Slider_delt.step = 0.1;
67 Slider_delt.value = Text_delt.value;
68
69 Slider_m.min = 0.1;
70 Slider_m.max = 10;
71 Slider_m.step = 0.1;
72 Slider_m.value = Text_m.value;
73
74 Slider_c.min = 1;
75 Slider_c.max = 200;
76 Slider_c.step = 1;
77 Slider_c.value = Text_c.value;
78 Slider_delt.focus();
79
80 // *** Задание вычислительных параметров ***
81
82 const fps = 550; // frames per second - число кадров в секунду (качеcтво отображения)
83 const spf = 260; // steps per frame - число шагов интегрирования между кадрами (скорость расчета)
84 const dt = 0.1 * T0 / fps; // шаг интегрирования
85
86 // Задание констант для рисования
87 const scale = canvas.height / Ny / a0; // масштабный коэффициент для перехода от расчетных к экранным координатам
88 const scale_gr = canvas_gr.height / Ny / a0; // масштабный коэффициент для перехода от расчетных к экранным координатам
89 const scale_gr2 = canvas_gr2.height / Ny / a0;
90
91
92 var w = canvas.width / scale; // ширина окна в расчетных координатах
93 var h = canvas.height / scale; // высота окна в расчетных координатах
94 var w1 = canvas_gr.width / scale; // ширина окна в расчетных координатах
95 var h1 = canvas_gr.height / scale; // высота окна в расчетных координатах
96
97
98 // ------------------------------- Выполнение программы ------------------------------------------
99 // Добавление шара 1
100 var b = [];
101 var time = 1;
102 b.x = l1; b.y = h / 2; // расчетные координаты шара
103 b.x_ = b.x; b.y_ = b.y;
104 b.fx = 0; b.vx = 0; // начальная скорость
105 b.cx = 0; b.ax = 0; // начальное ускорение
106
107 // центр рамки
108 var origin = [];
109 origin.x = w/2; origin.y = h/2;
110 // стенка
111 var wall1 = [];
112 wall1.x = w/2 - 9*a0; wall1.y = h/2;
113
114 // Основной цикл программы
115 setInterval(control, 1500 / fps); // функция control вызывается с периодом, определяемым вторым параметром
116
117 // ---------------------------------------------------------------------------------------------------------------------
118 // --------------------------------- Определение всех функций -----------------------------------
119 // ---------------------------------------------------------------------------------------------------------------------
120
121 // функция запускается при нажатии клавиши мыши
122 canvas.onmousedown = function(e)
123 {
124 var m = mouseCoords(e); // получаем координаты курсора мыши
125 context.clearRect(0, 0, w * scale, h* scale);
126 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
127 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
128 context_gr.closePath();
129 context_gr2.closePath();
130 context.closePath();
131 context.fill();
132 var x = b.x*scale - m.x; // расстояние от центра шара до курсора по оси x
133 var y = b.y*scale - m.y; // расстояние от центра шара до курсора по оси y
134 var rLen2 = x * x + y * y; // квадрат расстояния между курсором и центром шара
135 //console.log(rLen2);
136 //console.log(100*r*r);
137 if (rLen2 <= 500 * r * r) // если курсор нажал на шар
138 {
139 xShift = b.x*scale - m.x; // сдвиг курсора относительно центра шара по x
140 canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
141
142 }
143 }
144
145
146 // функция запускается при отпускании клавиши мыши
147 document.onmouseup = function()
148 {
149 canvas.onmousemove = null; // когда клавиша отпущена - функции перемещения нету
150 }
151
152 // функция запускается при перемещении мыши (много раз, в каждый момент перемещения)
153 // в нашем случае работает только с зажатой клавишей мыши
154 function mouseMove(e) {
155 context.clearRect(0, 0, w * scale, h* scale);
156 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
157 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
158 var m = mouseCoords(e); // получаем координаты курсора мыши
159 b.x = (m.x + xShift)/scale;
160 delt = b.x - l1;
161 b.vx = 0;
162 b.ax = 0;
163 //console.log(b.x);
164 Text_delt.value = delt;
165 Slider_delt.value = Text_delt.value;
166 //var scale1 = 0.0000000002;
167 //var scale2 = 0.2;
168
169 }
170
171 // функция возвращает координаты курсора мыши
172 function mouseCoords(e) {
173 var m = [] ;
174 var rect = canvas.getBoundingClientRect();
175 m.x = e.clientX - rect.left;
176 m.y = e.clientY - rect.top;
177 return m;
178 }
179 // основная функция, вызываемая в программе
180 function control()
181 {
182 physics(); // делаем spf шагов интегрирование
183 draw();
184 draw_gr();
185 draw_gr2();
186
187 }
188
189 // Реакция на изменение значения в чекбоксе
190 this.set_delt = function(input)
191 {
192 delt = Number(input); //записываем значение начального смещения
193 time = 1;
194 b.x = l1 + delt; //изменение начальных координат шаров
195 b.x_ = b.x;
196 b.vx = 0; //задание начальных скоростей шаров
197 b.ax = 0;
198 Text_delt.value = delt;
199 Slider_delt.value = Text_delt.value;
200 context.clearRect(0, 0, w * scale, h* scale);
201 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
202 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
203
204 }
205
206 this.set_m = function(input)
207 {
208 m = Number(input);
209 time = 1;
210 context.clearRect(0, 0, w * scale, h* scale);
211 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
212 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
213 }
214
215 this.set_c = function(input)
216 {
217 c = Number(input);
218 time = 1;
219 context.clearRect(0, 0, w * scale, h* scale);
220 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
221 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
222
223 }
224
225 this.set_b1 = function(input)
226 {
227 b1 = Number(input);
228 time = 1;
229 context.clearRect(0, 0, w * scale, h* scale);
230 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
231 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
232 }
233
234 this.set_b3 = function(input)
235 {
236 b3 = Number(input);
237 time = 1;
238 context.clearRect(0, 0, w * scale, h* scale);
239 context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
240 context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr);
241 }
242
243 /*this.set_scale1 = function(input)
244 {
245 //scale1 = Number(input);
246 var Cmax = Math.max(c1, c2); var Mmax = Math.max(m1, m2);
247 scale1 = h*Mmax/(Cmax*delt);
248 console.log(scale1);
249 time = 1;
250 context.clearRect(0, 0, w * scale, h * scale);
251 context_gr.clearRect(0, 0, w * scale, h * scale);
252 context_gr2.clearRect(0, 0, w * scale, h * scale);
253 }
254
255 this.set_scale2 = function(input)
256 {
257
258 scale2 = Number(input);
259 time = 1;
260 context.clearRect(0, 0, w * scale, h * scale);
261 context_gr.clearRect(0, 0, w * scale, h * scale);
262 context_gr2.clearRect(0, 0, w * scale, h * scale);
263 }*/
264 // Функция, делающая spf шагов интегрирования
265 function physics()
266 {
267 b.x_ = b.x; b.vx_= b.vx; b.ax_ = b.ax; //записываем старые координаты, скорости и ускорения
268 //c.x_ = c.x; c.vx_= c.vx;
269 E_ = E;
270 for (var s = 1; s <= spf; s++)
271 {
272 b.ax = 1*(-c*(b.x - l1) + b1*b.vx - b3*b.vx*b.vx*b.vx )/m*dt; //расчет ускорения первого шара
273 //console.log(Ftr);
274 //console.log(b.vx);
275 /* c.vx += -c2*(c.x - b.x - l2)/m2*dt; //расчет скорости второго шара */
276 b.vx += 100*b.ax*dt; //расчет скорости первого шара
277 b.x += b.vx*dt
278 /* c.x += c.vx*dt; */ //расчет координаты второго шара
279 //console.log(b.x - 2*a0)
280 /* if (b.x - 2*a0 > w/2 - 9*a0) // условие на пружину сжатую.
281 {
282 b.x += 10000*b.vx*dt ;
283 console.log(b.x);
284 } // расчет координаты первого шара
285 else
286 {
287 b.vx = 0 ;
288 b.ax = 0;
289
290 for (var s = 1; s <= spf; s++)
291 {
292 b.ax = 100*(-c1*(b.x - l1)+ k*b.vx - Ftr)/m1*dt; //расчет ускорения первого шара
293 console.log(b.x)
294 b.vx += b.ax*dt;
295 b.x += b.vx*dt; */
296 /* } */
297 }
298
299 //console.log(b.x)
300 E = 0.5*c*(b.x-l1)*(b.x - l1); //рачсет энергии системы
301 //Vprov = Math.max(b.vx, c.vx);
302 //if ((Vprov) > Vmax) Vmax = b.vx;
303
304
305
306
307 time = time + 1;
308
309 }
310
311 // определение функций, рисующих частицу, стенки и графики
312
313 function draw() //функция, рисующая шары, стенку и пружины
314 {
315 context.clearRect(0, 0, w * scale, h * scale); // очистить экран
316
317 // линия, соединяющая первую частицу со стенкой
318 context.beginPath();
319 context.moveTo(b.x*scale, b.y*scale);
320 context.lineTo(wall1.x*scale, wall1.y*scale);
321 // стенка
322 context.moveTo(wall1.x*scale, (wall1.y + a0)*scale );
323 context.lineTo(wall1.x*scale, (wall1.y - a0)*scale );
324 context.closePath();
325 context.stroke();
326
327 //частица первая
328 context.fillStyle = 'blue';
329 context.beginPath();
330 context.arc(b.x * scale, b.y * scale, 0.5*r * scale, 0, 2*Math.PI, false);
331 context.fill();
332
333
334 }
335
336
337
338 function draw_gr() // Определение функции, рисующей первый график
339 {
340 scale2 = h /5* delt;
341 //console.log (Math.abs(b.vx_ - b.vx));
342 if(Math.abs(b.vx_ - b.vx) > 0.00005)
343 {
344 Graph(b, 'blue'); //график для шара при положительном ускорении
345 }
346 else
347 {
348 Graph(b, 'red'); //график для шара при отрицательном ускорении
349 }
350 GraphAxex('black'); //оси
351
352
353
354 }
355
356
357
358
359 function Graph(b, color)
360 {
361 context_gr2.lineWidth = 2;
362 context_gr.strokeStyle = color;
363 context_gr.beginPath();
364 context_gr.moveTo(time*scale2/3, (b.x-l1)*scale*2*scale2 + h1*scale/2);
365 context_gr.lineTo( (time+1)*scale2/3, (b.x_- l1)*scale*2*scale2 + h1*scale/2);
366 context_gr.stroke();
367 context_gr.closePath();
368
369 }
370
371 function GraphAxex(color)
372 {
373 context_gr2.lineWidth = 2;
374 context_gr.strokeStyle = color;
375 context_gr.beginPath();
376 // ось горизонтальная
377 context_gr.moveTo(w1/2*scale, 0);
378 context_gr.lineTo(w1/2*scale, h1*scale);
379 // ось вертикальная
380 context_gr.moveTo(0, (h1/2)*scale);
381 context_gr.lineTo((w1)*scale, (h1/2)*scale);
382 context_gr.closePath();
383 context_gr.stroke();
384
385 }
386
387 function Graph1(b, color)
388 {
389 context_gr2.lineWidth = 2;
390 context_gr.strokeStyle = color;
391 context_gr.beginPath();
392 context_gr.moveTo(time*scale2/3, (b.x-l1)*scale*2*scale2 + scale*h1/2);
393 context_gr.lineTo( (time+1)*scale2/3, (b.x_- l1)*scale*2*scale2 + scale*h1/2);
394 context_gr.stroke();
395 context_gr.closePath();
396
397 }
398
399
400 function draw_gr2() // Определение функции, рисующей второй график
401 {
402
403 scale1 = 6* (h1*Mmax)/( c*delt*delt);
404 scale2 = A;
405 GraphVel(b, 'blue'); //график для шара
406 //GraphVel2(b, 'red'); //график для амплитудного коэффициента для шара
407 GraphVel3(b, 'green');
408 GraphAxex2('black'); //оси
409 //console.log(A);
410
411
412 }
413
414 /* function draw_gr3() // Определение функции, рисующей амплитудный график сходимости
415 {
416
417 var A = Math.sqrt((-4*b1)m*m/(3*b3*c*c));
418 scale1 = A;
419 GraphVel(b, 'yellow'); //график для первого шара
420 //GraphVel2(c, 'red'); //график для второго шара
421 GraphAxex2('black'); //оси
422
423
424 } */
425
426
427
428 function GraphVel(b, color)
429 {
430
431 context_gr2.lineWidth = 2;
432 context_gr2.strokeStyle = color;
433
434 context_gr2.beginPath();
435
436 context_gr2.moveTo((b.x-l1)*2*scale1 + scale*w1/2, b.vx*scale1 + scale*h1/2 );
437 context_gr2.lineTo((b.x_- l1)*2*scale1 + scale*w1/2, b.vx_*scale1 + scale*h1/2);
438
439 context_gr2.closePath();
440 context_gr2.stroke();
441
442
443 }
444
445 function GraphVel2(b, color)
446 {
447 context_gr2.lineWidth = 2;
448 context_gr2.strokeStyle = color;
449
450 context_gr2.beginPath();
451
452 context_gr2.moveTo((b.x-l1)*2*scale2 + scale*w1/2, b.vx*scale2 + scale*h1/2 );
453 context_gr2.lineTo((b.x_- l1)*2*scale2 + scale*w1/2, b.vx_*scale2 + scale*h1/2);
454
455 context_gr2.closePath();
456 context_gr2.stroke();
457
458
459
460 }
461 function GraphVel3(b, color)
462
463 {
464
465 //Grafic A
466 A = Math.sqrt((-4*b1*m*m)/(3*b3*c*c));
467 context_gr2.lineWidth = 1;
468 context_gr2.strokeStyle = color;
469 console.log(A);
470 context_gr2.beginPath();
471
472 context_gr2.moveTo(1*A*Math.sin(time)+ scale*w1/2, 1*A*Math.cos(time)+ scale*h1/2);
473 context_gr2.lineTo(1*A*Math.sin(time)+ scale*w1/2, 1*A*Math.cos(time)+ scale*h1/2);
474 //context_gr2.moveTo(A*Math.sin(b.x-l1)+ scale*w1/2, A*Math.cos(b.x-l1)+ (h1/2)*scale);
475 //context_gr2.lineTo(A*Math.sin(b.x_-l1)+ scale*w1/2,A*Math.cos(b.x_-l1) + (h1/2)*scale);
476
477 context_gr2.closePath();
478 context_gr2.stroke();
479 }
480
481 function GraphAxex2(color)
482 {
483 context_gr2.lineWidth = 1;
484 context_gr2.strokeStyle = color;
485 context_gr2.beginPath();
486 // ось горизонтальная
487 context_gr2.moveTo(w1/2*scale, 0);
488 context_gr2.lineTo(w1/2*scale, h1*scale);
489 // ось вертикальная
490 context_gr2.moveTo(0, (h1/2)*scale);
491 context_gr2.lineTo((w1)*scale, (h1/2)*scale);
492 context_gr2.closePath();
493 context_gr2.stroke();
494
495 }
496
497
498 }
Файл "1_7.html"
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title> 2 </title>
5 <script src="2_7.js"></script>
6 </head>
7 <body>
8 <!-- Добавление области для рисования частицы -->
9 <canvas id="canvasBalls" width="800" height="300" style="border:1px solid #000000;"></canvas>
10 <!-- Добавление области для рисования графика -->
11 <div>
12 Координаты от времени:
13 <font color="#0000FF" size="5"><B>—</B></font> Тело
14
15 </div>
16 <canvas id="canvasGraph" width="800" height="600" style="border:1px solid #000000;"></canvas>
17 <!-- Добавление чекбокса для ввода скорости частицы -->
18 <div>
19 Фазовая плоскость:
20 <font color="#0000FF" size="5"><B>—</B></font> Тело
21
22 </div>
23 <canvas id="canvasGraph1" width="800" height="600" style="border:1px solid #000000;"></canvas>
24
25 <div>
26 delt =
27 <input id="Text_delt" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput="
28 if (!this.checkValidity()) return;
29 app.set_delt(this.value);
30 document.getElementById('Slider_delt').value = this.value;
31
32 ">
33 <input type = "range" id="Slider_delt" style="width: 100px;" oninput="app.set_delt(this.value); document.getElementById('Text_delt').value = this.value;">
34 </I></font>
35 </div>
36
37 <!-- Масса 1 -->
38 <div>
39 m =
40 <input id="Text_m" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput="
41 if (!this.checkValidity()) return;
42 app.set_m(this.value);
43 document.getElementById('Slider_m').value = this.value;
44 ">
45 <input type = "range" id="Slider_m" style="width: 100px;" oninput="app.set_m(this.value); document.getElementById('Text_m').value = this.value;">
46 </I></font>
47 </div>
48
49 <!-- Жесткость 1-->
50 <div>
51 c =
52 <input id="Text_c" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput="
53 if (!this.checkValidity()) return;
54 app.set_c(this.value);
55 document.getElementById('Slider_c').value = this.value;
56 ">
57 <input type = "range" id="Slider_c" style="width: 100px;" oninput="app.set_c(this.value); document.getElementById('Text_c').value = this.value;">
58 </I></font>
59 </div>
60 <!-- Первый коэффициент -->
61 <div>
62 b1 =
63 <input id="Text_b1" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput="
64 if (!this.checkValidity()) return;
65 app.set_b1(this.value);
66 document.getElementById('Slider_b1').value = this.value;
67
68 ">
69 <input type = "range" id="Slider_b1" style="width: 100px;" oninput="app.set_b1(this.value); document.getElementById('Text_b1').value = this.value;">
70 </I></font>
71 </div>
72
73 <!-- Второй коэффициент -->
74 <div>
75 b3 =
76 <input id="Text_b3" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput="
77 if (!this.checkValidity()) return;
78 app.set_b3(this.value);
79 document.getElementById('Slider_b3').value = this.value;
80
81 ">
82 <input type = "range" id="Slider_b3" style="width: 100px;" oninput="app.set_b3(this.value); document.getElementById('Text_b3').value = this.value;">
83 </I></font>
84 </div>
85 <script type="text/javascript"> app = new MainParticle(document.getElementById('canvasBalls'),document.getElementById('canvasGraph'),document.getElementById('canvasGraph1'));</script>
86 </body>
87 </html>