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