Интерактивная модель простейшей автоколебательной системы с пружиной — различия между версиями
Материал из Department of Theoretical and Applied Mechanics
(Новая страница: «Виртуальная лаборатория > Простейшая колебательная система с двумя степенями свобод…») |
|||
Строка 7: | Строка 7: | ||
m \ddot{z} + F'(V) \dot{z} + c z = 0 | m \ddot{z} + F'(V) \dot{z} + c z = 0 | ||
</math> | </math> | ||
+ | |||
+ | Скачать [[Медиа:IMoS-OSWaS.rar|IMoS-OSWaS.rar]]. | ||
+ | |||
+ | <div class="mw-collapsible mw-collapsed" style="width:100%" > | ||
+ | '''Текст программы на языке JavaScript (разработчик [[Сергей Бондарев]]):''' <div class="mw-collapsible-content"> | ||
+ | Файл '''"2_1.js"''' | ||
+ | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
+ | |||
+ | function MainParticle(canvas, canvas_gr, canvas_gr2) { | ||
+ | // Предварительные установки | ||
+ | var context = canvas.getContext("2d"); // на context происходит рисование | ||
+ | var context_gr = canvas_gr.getContext("2d"); // на context происходит рисование | ||
+ | var context_gr2 = canvas_gr2.getContext("2d"); | ||
+ | |||
+ | // Задание констант | ||
+ | const Pi = 3.1415926; // число "пи" | ||
+ | const m0 = 1; // масштаб массы | ||
+ | const T0 = 1; // масштаб времени (период колебаний исходной системы) | ||
+ | const a0 = 1; // масштаб расстояния (диаметр шара) | ||
+ | |||
+ | const g0 = a0 / T0 / T0; // масштаб ускорения (ускорение, при котором за T0 будет пройдено расстояние a0) | ||
+ | const k0 = 2 * Pi / T0; // масштаб частоты | ||
+ | const C0 = m0 * k0 * k0; // масштаб жесткости | ||
+ | var scale1 = 0.2; | ||
+ | var scale2 = 0.2; | ||
+ | |||
+ | |||
+ | // *** Задание физических параметров *** | ||
+ | var xShift= 0; | ||
+ | const Ny = 15; // число шаров, помещающихся по вертикали в окно (задает размер шара относительно размера окна) | ||
+ | const Nx = 15; // число шаров, помещающихся по вертикали в окно (задает размер шара относительно размера окна) | ||
+ | const l1 = 15*a0; // длина первой пружины | ||
+ | const l2 = 5*a0; // длина второй пружины | ||
+ | var m1 = 5 * m0; // масса первого шара | ||
+ | var m2 = 10 * m0; // масса второго шара | ||
+ | const Cwall = 10 * C0; // жесткость стен | ||
+ | const r = 1 * a0; // радиус частицы в расчетных координатах | ||
+ | var c1 = 100; // "жесткость" пружинки 1 | ||
+ | var c2 = 100; // "жесткость" пружинки 1 | ||
+ | var vx0 = 0 * a0/T0; //начальная скорость | ||
+ | var delt = 0*a0; //начальное смещение | ||
+ | var E = 0; //энергия системы | ||
+ | var Vmax = 0; var Mmin = 0; var Vprov = 0; | ||
+ | |||
+ | |||
+ | //*** Передача значений слайдерам и текстовым окнам*** | ||
+ | Text_delt.value = delt; | ||
+ | Text_m1.value = m1; | ||
+ | //Text_m2.value = m2; | ||
+ | Text_c1.value = c1; | ||
+ | //Text_c2.value = c2; | ||
+ | |||
+ | Slider_delt.min = -1; | ||
+ | Slider_delt.max = 1; | ||
+ | Slider_delt.step = 0.1; | ||
+ | Slider_delt.value = Text_delt.value; | ||
+ | |||
+ | Slider_m1.min = 0.1; | ||
+ | Slider_m1.max = 10; | ||
+ | Slider_m1.step = 0.1; | ||
+ | Slider_m1.value = Text_m1.value; | ||
+ | |||
+ | //Slider_m2.min = 0.1; | ||
+ | //Slider_m2.max = 10; | ||
+ | //Slider_m2.step = 0.1; | ||
+ | // Slider_m2.value = Text_m2.value; | ||
+ | |||
+ | //Slider_c2.min = 1; | ||
+ | // Slider_c2.max = 200; | ||
+ | // Slider_c2.step = 1; | ||
+ | //Slider_c2.value = Text_c2.value; | ||
+ | Slider_c1.min = 1; | ||
+ | Slider_c1.max = 200; | ||
+ | Slider_c1.step = 1; | ||
+ | Slider_c1.value = Text_c1.value; | ||
+ | Slider_delt.focus(); | ||
+ | |||
+ | // *** Задание вычислительных параметров *** | ||
+ | |||
+ | const fps = 550; // frames per second - число кадров в секунду (качеcтво отображения) | ||
+ | const spf = 260; // steps per frame - число шагов интегрирования между кадрами (скорость расчета) | ||
+ | const dt = 0.01 * T0 / fps; // шаг интегрирования | ||
+ | |||
+ | // Задание констант для рисования | ||
+ | const scale = canvas.height / Ny / a0; // масштабный коэффициент для перехода от расчетных к экранным координатам | ||
+ | const scale_gr = canvas_gr.height / Ny / a0; // масштабный коэффициент для перехода от расчетных к экранным координатам | ||
+ | const scale_gr2 = canvas_gr2.height / Ny / a0; | ||
+ | |||
+ | |||
+ | var w = canvas.width / scale; // ширина окна в расчетных координатах | ||
+ | var h = canvas.height / scale; // высота окна в расчетных координатах | ||
+ | var w1 = canvas_gr.width / scale; // ширина окна в расчетных координатах | ||
+ | var h1 = canvas_gr.height / scale; // высота окна в расчетных координатах | ||
+ | |||
+ | |||
+ | // ------------------------------- Выполнение программы ------------------------------------------ | ||
+ | // Добавление шара 1 | ||
+ | var b = []; | ||
+ | var time = 1; | ||
+ | b.x = l1; b.y = h / 2; // расчетные координаты шара | ||
+ | b.x_ = b.x; b.y_ = b.y; | ||
+ | b.fx = 0; b.vx = 0; // начальная скорость | ||
+ | // Добавление шара 2 | ||
+ | var c = []; | ||
+ | c.x = l2 + l1; c.y = h / 2; // расчетные координаты шара | ||
+ | c.x_ = c.x; c.y_ = c.y; | ||
+ | c.fx = 0; c.vx = 0; // начальная скорость | ||
+ | |||
+ | |||
+ | // центр рамки | ||
+ | var origin = []; | ||
+ | origin.x = w/2; origin.y = h/2; | ||
+ | // стенка | ||
+ | var wall1 = []; | ||
+ | wall1.x = w/2 - 9*a0; wall1.y = h/2; | ||
+ | |||
+ | // Основной цикл программы | ||
+ | setInterval(control, 1500 / fps); // функция control вызывается с периодом, определяемым вторым параметром | ||
+ | |||
+ | // --------------------------------------------------------------------------------------------------------------------- | ||
+ | // --------------------------------- Определение всех функций ----------------------------------- | ||
+ | // --------------------------------------------------------------------------------------------------------------------- | ||
+ | |||
+ | // функция запускается при нажатии клавиши мыши | ||
+ | canvas.onmousedown = function(e) | ||
+ | { | ||
+ | var m = mouseCoords(e); // получаем координаты курсора мыши | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr.closePath(); | ||
+ | context_gr2.closePath(); | ||
+ | context.closePath(); | ||
+ | context.fill(); | ||
+ | var x = b.x*scale - m.x; // расстояние от центра шара до курсора по оси x | ||
+ | var y = b.y*scale - m.y; // расстояние от центра шара до курсора по оси y | ||
+ | var rLen2 = x * x + y * y; // квадрат расстояния между курсором и центром шара | ||
+ | //console.log(rLen2); | ||
+ | //console.log(100*r*r); | ||
+ | if (rLen2 <= 500 * r * r) // если курсор нажал на шар | ||
+ | { | ||
+ | xShift = b.x*scale - m.x; // сдвиг курсора относительно центра шара по x | ||
+ | canvas.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | // функция запускается при отпускании клавиши мыши | ||
+ | document.onmouseup = function() | ||
+ | { | ||
+ | canvas.onmousemove = null; // когда клавиша отпущена - функции перемещения нету | ||
+ | } | ||
+ | |||
+ | // функция запускается при перемещении мыши (много раз, в каждый момент перемещения) | ||
+ | // в нашем случае работает только с зажатой клавишей мыши | ||
+ | function mouseMove(e) { | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | var m = mouseCoords(e); // получаем координаты курсора мыши | ||
+ | b.x = (m.x + xShift)/scale; | ||
+ | delt = b.x - l1; | ||
+ | b.vx = 0; c.vx = 0; | ||
+ | console.log(b.x); | ||
+ | Text_delt.value = delt; | ||
+ | Slider_delt.value = Text_delt.value; | ||
+ | //var scale1 = 0.0000000002; | ||
+ | //var scale2 = 0.2; | ||
+ | |||
+ | } | ||
+ | |||
+ | // функция возвращает координаты курсора мыши | ||
+ | function mouseCoords(e) { | ||
+ | var m = [] ; | ||
+ | var rect = canvas.getBoundingClientRect(); | ||
+ | m.x = e.clientX - rect.left; | ||
+ | m.y = e.clientY - rect.top; | ||
+ | return m; | ||
+ | } | ||
+ | // основная функция, вызываемая в программе | ||
+ | function control() | ||
+ | { | ||
+ | physics(); // делаем spf шагов интегрирование | ||
+ | draw(); | ||
+ | draw_gr(); | ||
+ | draw_gr2(); | ||
+ | |||
+ | } | ||
+ | |||
+ | // Реакция на изменение значения в чекбоксе | ||
+ | this.set_delt = function(input) | ||
+ | { | ||
+ | delt = Number(input); //записываем значение начального смещения | ||
+ | time = 1; | ||
+ | b.x = l1 + delt; c.x = l1+l2; //изменение начальных координат шаров | ||
+ | b.x_ = b.x; | ||
+ | b.vx = 0; c.vx = 0; //задание начальных скоростей шаров | ||
+ | Text_delt.value = delt; | ||
+ | Slider_delt.value = Text_delt.value; | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | |||
+ | } | ||
+ | |||
+ | this.set_m1 = function(input) | ||
+ | { | ||
+ | m1 = Number(input); | ||
+ | time = 1; | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | } | ||
+ | |||
+ | this.set_c1 = function(input) | ||
+ | { | ||
+ | c1 = Number(input); | ||
+ | time = 1; | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | |||
+ | } | ||
+ | |||
+ | this.set_m2 = function(input) | ||
+ | { | ||
+ | m2 = Number(input); | ||
+ | time = 1; | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | } | ||
+ | |||
+ | this.set_c2 = function(input) | ||
+ | {; | ||
+ | c2 = Number(input); | ||
+ | time = 1; | ||
+ | context.clearRect(0, 0, w * scale, h* scale); | ||
+ | context_gr.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | context_gr2.clearRect(0, 0, w1 * scale_gr, h1 * scale_gr); | ||
+ | } | ||
+ | |||
+ | /*this.set_scale1 = function(input) | ||
+ | { | ||
+ | //scale1 = Number(input); | ||
+ | var Cmax = Math.max(c1, c2); var Mmax = Math.max(m1, m2); | ||
+ | scale1 = h*Mmax/(Cmax*delt); | ||
+ | console.log(scale1); | ||
+ | time = 1; | ||
+ | context.clearRect(0, 0, w * scale, h * scale); | ||
+ | context_gr.clearRect(0, 0, w * scale, h * scale); | ||
+ | context_gr2.clearRect(0, 0, w * scale, h * scale); | ||
+ | } | ||
+ | |||
+ | this.set_scale2 = function(input) | ||
+ | { | ||
+ | |||
+ | scale2 = Number(input); | ||
+ | time = 1; | ||
+ | context.clearRect(0, 0, w * scale, h * scale); | ||
+ | context_gr.clearRect(0, 0, w * scale, h * scale); | ||
+ | context_gr2.clearRect(0, 0, w * scale, h * scale); | ||
+ | }*/ | ||
+ | |||
+ | // Функция, делающая spf шагов интегрирования | ||
+ | function physics() | ||
+ | { | ||
+ | b.x_ = b.x; b.vx_= b.vx; //записываем старые координаты и скорости | ||
+ | c.x_ = c.x; c.vx_= c.vx; | ||
+ | E_ = E; | ||
+ | |||
+ | for (var s = 1; s <= spf; s++) | ||
+ | { | ||
+ | |||
+ | b.vx += (c2*(-b.x + c.x - l2) - c1*(b.x - l1))/m1*dt; //расчет скорости первого шара | ||
+ | c.vx += -c2*(c.x - b.x - l2)/m2*dt; //расчет скорости второго шара | ||
+ | b.x += b.vx*dt; //расчет координаты первого шара | ||
+ | c.x += c.vx*dt; //расчет координаты второго шара | ||
+ | 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); //рачсет энергии системы | ||
+ | //Vprov = Math.max(b.vx, c.vx); | ||
+ | //if ((Vprov) > Vmax) Vmax = b.vx; | ||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | time = time + 1; | ||
+ | |||
+ | } | ||
+ | |||
+ | // определение функций, рисующих частицу, стенки и графики | ||
+ | |||
+ | function draw() //функция, рисующая шары, стенку и пружины | ||
+ | { | ||
+ | context.clearRect(0, 0, w * scale, h * scale); // очистить экран | ||
+ | |||
+ | // линия, соединяющая первую частицу со стенкой | ||
+ | context.beginPath(); | ||
+ | context.moveTo(b.x*scale, b.y*scale); | ||
+ | context.lineTo(wall1.x*scale, wall1.y*scale); | ||
+ | // линия, соединяющая первую частицу со второй | ||
+ | /* context.moveTo(b.x*scale, b.y*scale); | ||
+ | context.lineTo(c.x*scale, c.y*scale); */ | ||
+ | // стенка | ||
+ | context.moveTo(wall1.x*scale, (wall1.y + a0)*scale ); | ||
+ | context.lineTo(wall1.x*scale, (wall1.y - a0)*scale ); | ||
+ | context.closePath(); | ||
+ | context.stroke(); | ||
+ | |||
+ | // частица вторая | ||
+ | /* context.fillStyle = "red"; | ||
+ | context.beginPath(); | ||
+ | context.arc(c.x * scale, c.y * scale, 0.5*r * scale, 0, 2*Math.PI, false); | ||
+ | context.fill(); */ | ||
+ | //частица первая | ||
+ | context.fillStyle = 'blue'; | ||
+ | context.beginPath(); | ||
+ | context.arc(b.x * scale, b.y * scale, 0.5*r * scale, 0, 2*Math.PI, false); | ||
+ | context.fill(); | ||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | function draw_gr() // Определение функции, рисующей первый график | ||
+ | { | ||
+ | scale2 = h /5* delt; | ||
+ | //Graph1(c, 'red'); //график для второго шара | ||
+ | Graph(b, 'blue'); //график для первого шара | ||
+ | GraphAxex('black'); //оси | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | function Graph(b, color) | ||
+ | { | ||
+ | |||
+ | context_gr.strokeStyle = color; | ||
+ | context_gr.beginPath(); | ||
+ | context_gr.moveTo(time*scale2/3, (b.x-l1)*scale*2*scale2 + h1*scale/2); | ||
+ | context_gr.lineTo( (time+1)*scale2/3, (b.x_- l1)*scale*2*scale2 + h1*scale/2); | ||
+ | context_gr.stroke(); | ||
+ | context_gr.closePath(); | ||
+ | |||
+ | } | ||
+ | |||
+ | function GraphAxex(color) | ||
+ | { | ||
+ | context_gr.strokeStyle = color; | ||
+ | context_gr.beginPath(); | ||
+ | // ось горизонтальная | ||
+ | context_gr.moveTo(w1/2*scale, 0); | ||
+ | context_gr.lineTo(w1/2*scale, h1*scale); | ||
+ | // ось вертикальная | ||
+ | context_gr.moveTo(0, (h1/2)*scale); | ||
+ | context_gr.lineTo((w1)*scale, (h1/2)*scale); | ||
+ | context_gr.closePath(); | ||
+ | context_gr.stroke(); | ||
+ | |||
+ | } | ||
+ | |||
+ | function Graph1(b, color) | ||
+ | { | ||
+ | |||
+ | context_gr.strokeStyle = color; | ||
+ | context_gr.beginPath(); | ||
+ | context_gr.moveTo(time*scale2/3, (b.x-l1-l2)*scale*2*scale2 + scale*h1/2); | ||
+ | context_gr.lineTo( (time+1)*scale2/3, (b.x_- l1-l2)*scale*2*scale2 + scale*h1/2); | ||
+ | context_gr.stroke(); | ||
+ | context_gr.closePath(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | function draw_gr2() // Определение функции, рисующей второй график | ||
+ | { | ||
+ | |||
+ | var Mmax= Math.max(m1, m2); | ||
+ | scale1 = 6* (h1*Mmax)/( (c1+c2)*delt*delt); | ||
+ | GraphVel(b, 'blue'); //график для первого шара | ||
+ | //GraphVel2(c, 'red'); //график для второго шара | ||
+ | GraphAxex2('black'); //оси | ||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | function GraphVel(b, color) | ||
+ | { | ||
+ | |||
+ | |||
+ | context_gr2.strokeStyle = color; | ||
+ | |||
+ | context_gr2.beginPath(); | ||
+ | |||
+ | context_gr2.moveTo((b.x-l1)*2*scale1 + scale*w1/2, b.vx*scale1 + scale*h1/2 ); | ||
+ | context_gr2.lineTo((b.x_- l1)*2*scale1 + scale*w1/2, b.vx_*scale1 + scale*h1/2); | ||
+ | |||
+ | context_gr2.closePath(); | ||
+ | context_gr2.stroke(); | ||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | function GraphVel2(b, color) | ||
+ | { | ||
+ | |||
+ | context_gr2.strokeStyle = color; | ||
+ | |||
+ | context_gr2.beginPath(); | ||
+ | |||
+ | context_gr2.moveTo((b.x-l1-l2)*2*scale1 + scale*w1/2, b.vx*scale1 + scale*h1/2 ); | ||
+ | context_gr2.lineTo((b.x_- l1-l2)*2*scale1 + scale*w1/2, b.vx_*scale1 + scale*h1/2); | ||
+ | |||
+ | |||
+ | context_gr2.closePath(); | ||
+ | context_gr2.stroke(); | ||
+ | |||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | function GraphAxex2(color) | ||
+ | { | ||
+ | context_gr2.strokeStyle = color; | ||
+ | context_gr2.beginPath(); | ||
+ | // ось горизонтальная | ||
+ | context_gr2.moveTo(w1/2*scale, 0); | ||
+ | context_gr2.lineTo(w1/2*scale, h1*scale); | ||
+ | // ось вертикальная | ||
+ | context_gr2.moveTo(0, (h1/2)*scale); | ||
+ | context_gr2.lineTo((w1)*scale, (h1/2)*scale); | ||
+ | context_gr2.closePath(); | ||
+ | context_gr2.stroke(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Файл '''"1_1.html"''' | ||
+ | <syntaxhighlight lang="html5" line start="1" enclose="div"> | ||
+ | <!DOCTYPE html> | ||
+ | <html> | ||
+ | <head> | ||
+ | <title> 2 </title> | ||
+ | <script src="2_1.js"></script> | ||
+ | </head> | ||
+ | <body> | ||
+ | <!-- Добавление области для рисования частицы --> | ||
+ | <canvas id="canvasBalls" width="800" height="300" style="border:1px solid #000000;"></canvas> | ||
+ | <!-- Добавление области для рисования графика --> | ||
+ | <div> | ||
+ | Координаты от времени: | ||
+ | <font color="#0000FF" size="5"><B>—</B></font> Первое тело | ||
+ | |||
+ | <!-- <font color="#FF0000" size="5"><B>—</B></font> Второе тело --> | ||
+ | |||
+ | </div> | ||
+ | <canvas id="canvasGraph" width="800" height="600" style="border:1px solid #000000;"></canvas> | ||
+ | <!-- Добавление чекбокса для ввода скорости частицы --> | ||
+ | <div> | ||
+ | Фазовая плоскость: | ||
+ | <font color="#0000FF" size="5"><B>—</B></font> Первое тело | ||
+ | |||
+ | <!-- <font color="#FF0000" size="5"><B>—</B></font> Второе тело --> | ||
+ | |||
+ | </div> | ||
+ | <canvas id="canvasGraph1" width="800" height="600" style="border:1px solid #000000;"></canvas> | ||
+ | |||
+ | <div> | ||
+ | delt = | ||
+ | <input id="Text_delt" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput=" | ||
+ | if (!this.checkValidity()) return; | ||
+ | app.set_delt(this.value); | ||
+ | document.getElementById('Slider_delt').value = this.value; | ||
+ | |||
+ | "> | ||
+ | <input type = "range" id="Slider_delt" style="width: 100px;" oninput="app.set_delt(this.value); document.getElementById('Text_delt').value = this.value;"> | ||
+ | </I></font> | ||
+ | </div> | ||
+ | |||
+ | <!-- Масса 1 --> | ||
+ | <div> | ||
+ | m1 = | ||
+ | <input id="Text_m1" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput=" | ||
+ | if (!this.checkValidity()) return; | ||
+ | app.set_m1(this.value); | ||
+ | document.getElementById('Slider_m1').value = this.value; | ||
+ | "> | ||
+ | <input type = "range" id="Slider_m1" style="width: 100px;" oninput="app.set_m1(this.value); document.getElementById('Text_m1').value = this.value;"> | ||
+ | </I></font> | ||
+ | </div> | ||
+ | |||
+ | <!-- Жесткость 1--> | ||
+ | <div> | ||
+ | c1 = | ||
+ | <input id="Text_c1" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput=" | ||
+ | if (!this.checkValidity()) return; | ||
+ | app.set_c1(this.value); | ||
+ | document.getElementById('Slider_c1').value = this.value; | ||
+ | "> | ||
+ | <input type = "range" id="Slider_c1" style="width: 100px;" oninput="app.set_c1(this.value); document.getElementById('Text_c1').value = this.value;"> | ||
+ | </I></font> | ||
+ | </div> | ||
+ | |||
+ | <script type="text/javascript"> app = new MainParticle(document.getElementById('canvasBalls'),document.getElementById('canvasGraph'),document.getElementById('canvasGraph1'));</script> | ||
+ | </body> | ||
+ | </html> | ||
+ | </syntaxhighlight> | ||
+ | </div> | ||
+ | </div> | ||
+ | |||
+ | [[Category: Виртуальная лаборатория]] |
Версия 13:52, 5 февраля 2016
Виртуальная лаборатория > Простейшая колебательная система с двумя степенями свободыРассматривается простейшая колебательная система тело-пружина. Пружина заделана в стенку. Система колеблется под воздействием движущейся пластины.
Уравнения движения системы будут выглядеть так:
Скачать 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>