Difference between revisions of "Driven oscillations of a mass on a nonlinear spring"

From Department of Theoretical and Applied Mechanics
Jump to: navigation, search
Line 2: Line 2:
  
 
== Annotation to the project ==
 
== Annotation to the project ==
This project gives an idea about nonlinear oscillation of load with the periodic force acting on it.
+
This project gives an idea about nonlinear oscillation of the load with the periodic force acting on it.
  
 
== Formulation of the problem ==
 
== Formulation of the problem ==
Line 10: Line 10:
  
 
== Overview ==
 
== Overview ==
If the periodically changing external force is acting on the system, the system performs oscillations which repeat in different ways the nature of change of this force. Such oscillations are '''called forced'''.
+
If the periodically changing of the external force is acting on the system, the system performs oscillations which repeat the pattern of changes of this force. Such oscillations are '''called forced'''.
  
 
F0 is the force amplitude and the greatest value of the force.
 
F0 is the force amplitude and the greatest value of the force.
Line 32: Line 32:
 
<syntaxhighlight lang="javascript" enclose="div">
 
<syntaxhighlight lang="javascript" enclose="div">
  
    window.addEventListener("load", Main_Spring, true);
+
  window.addEventListener("load", Main_Spring, true);
 
     function Main_Spring() {
 
     function Main_Spring() {
 
     var canvas = spring_canvas;
 
     var canvas = spring_canvas;
     canvas.onselectstart = function () {return false;};    // prohibition selection canvas
+
     canvas.onselectstart = function () {return false;};    // запрет выделения canvas
     var ctx = canvas.getContext("2d");                      // at the ctx is drawing
+
     var ctx = canvas.getContext("2d");                      // на ctx происходит рисование
     var w = canvas.width;                                  // the width of the window in the calculated coordinates
+
     var w = canvas.width;                                  // ширина окна в расчетных координатах
     var h = canvas.height;                                  // the height of the window in the calculated coordinates
+
     var h = canvas.height;                                  // высота окна в расчетных координатах
     var Pi = 3.1415926;                             // Pi
+
     var Pi = 3.1415926;                                     // число "пи"
     var m0 = 1;                             // weight scale
+
     var m0 = 1;                                             // масштаб массы
     var T0 = 1;                             // time scale (the period of oscillation of the original system)
+
     var T0 = 1;                                             // масштаб времени (период колебаний исходной системы)
 
     var t = 0;
 
     var t = 0;
     var k0 = 2 * Pi / T0;                               // frequency scale
+
     var k0 = 2 * Pi / T0;                                   // масштаб частоты
     var C0 = m0 * k0 * k0;                             // hardness scale
+
     var C0 = m0 * k0 * k0;                                 // масштаб жесткости
     var B0 = 2 * m0 * k0;                           // viscosity scale
+
     var B0 = 2 * m0 * k0;                                   // масштаб вязкости
 
     var omega = 10;
 
     var omega = 10;
 
      
 
      
     // *** Creating the physical parameters***
+
     // *** Задание физических параметров ***
 
     var F = 80;
 
     var F = 80;
     var m = 1 * m0;                                     // weight
+
     var m = 1 * m0;                                         // масса
     var C = 1 * C0;                                     // rigidity
+
     var C = 1 * C0;                                         // жесткость
     var C1 = 1 * C0;                                     // rigidity1
+
     var C1 = 1 * C0;                                       // жесткость1
     var B = .1 * B0;                                     // viscosity
+
     var B = .1 * B0;                                       // вязкость
 
      
 
      
 
     slider_m.value = (m / m0).toFixed(1); number_m.value = (m / m0).toFixed(1);
 
     slider_m.value = (m / m0).toFixed(1); number_m.value = (m / m0).toFixed(1);
Line 61: Line 61:
 
     slider_F.value = (F / 40).toFixed(1); number_F.value = (F / 40).toFixed(1);
 
     slider_F.value = (F / 40).toFixed(1); number_F.value = (F / 40).toFixed(1);
  
     // *** Creating the parameters of computing ***
+
     // *** Задание вычислительных параметров ***
  
     var fps = 300;                   // frames per second
+
     var fps = 300;                                 // frames per second - число кадров в секунду (качечтво отображения)
     var spf = 100;                   // steps per frame  
+
     var spf = 100;                                 // steps per frame   - число шагов интегрирования между кадрами
     var dt  = 0.05 * T0 / fps;               // integration step (calculation quality)  
+
     var dt  = 0.05 * T0 / fps;                     // шаг интегрирования (качество расчета)
     var steps = 0;                                  // the number of integration steps
+
     var steps = 0;                                  // количество шагов интегрирования
  
 
     function setM(new_m) {m = new_m * m0;}
 
     function setM(new_m) {m = new_m * m0;}
Line 85: Line 85:
 
     number_F.oninput = function() {slider_F.value = number_F.value;      setF(number_F.value);};
 
     number_F.oninput = function() {slider_F.value = number_F.value;      setF(number_F.value);};
  
     var count = true;                  // system analysis
+
     var count = true;                  // проводить ли расчет системы
     var v = 0; // load speed
+
     var v = 0;                         // скорость тела
  
     var rw = canvas.width / 30;  
+
     var rw = canvas.width / 30;        
 
     var rh = canvas.height / 1.5;
 
     var rh = canvas.height / 1.5;
     var x0 = 15 * rw - rw / 2;    
+
     var x0 = 15 * rw - rw / 2;        
 
     var y0 = rh / 1.33 - rh / 2;
 
     var y0 = rh / 1.33 - rh / 2;
  
     // spring settings
+
     // параметры пружины
     var coil = 10;        // number of turns
+
     var coil = 10;        // количество витков
     var startX = 0;      // spring fastening
+
     var startX = 0;      // закрепление пружины
  
     // create a rectangle-cargo
+
     // создаем прямоугольник-грузик
 
     var rect = {
 
     var rect = {
 
         x: x0,  width: rw,
 
         x: x0,  width: rw,
         y: y0, height: rh,
+
         y: y0, height: rh,
         fill: "rgba(0, 0, 255, 1)"   // colour
+
         fill: "rgba(0, 0, 255, 1)"     // цвет
 
     };
 
     };
  
     // capture a rectangle with the mouse
+
     // захват прямоугольника мышью
     var mx_;                                    // buffer position of the mouse (to calculate the speed of the ball when released)
+
     var mx_;                                    // буфер позиции мыши (для расчета скорости при отпускании шара)
     document.onmousedown = function(e) {        // function by pressing the mouse button
+
     document.onmousedown = function(e) {        // функция при нажатии клавиши мыши
         var m = mouseCoords(e);                // we get estimated coordinates of the mouse cursor
+
         var m = mouseCoords(e);                // получаем расчетные координаты курсора мыши
 +
 
 
         var x = rect.x;
 
         var x = rect.x;
 
         var xw = rect.x + rect.width;
 
         var xw = rect.x + rect.width;
Line 113: Line 114:
 
         var yh = rect.y + rect.height;
 
         var yh = rect.y + rect.height;
 
         if (x <= m.x && xw >= m.x  && y <= m.y && yh >= m.y) {
 
         if (x <= m.x && xw >= m.x  && y <= m.y && yh >= m.y) {
             if (e.which == 1) {                        // left mouse button is pressed
+
             if (e.which == 1) {                        // нажата левая клавиша мыши
                 rect.xPlus = rect.x - m.x;              // cursor shift relative to the cargo on the x
+
                 rect.xPlus = rect.x - m.x;              // сдвиг курсора относительно грузика по x
                 rect.yPlus = rect.y - m.y;              // cursor shift relative to the cargo on the y
+
                 rect.yPlus = rect.y - m.y;              // сдвиг курсора относительно грузика по y
 
                 mx_ = m.x;
 
                 mx_ = m.x;
 
                 count = false;
 
                 count = false;
                 document.onmousemove = mouseMove;      // while a key is pressed, fanction of motions is correct
+
                 document.onmousemove = mouseMove;      // пока клавиша нажата - работает функция перемещения
 
             }
 
             }
 
         }
 
         }
 
     };
 
     };
  
     document.onmouseup = function(e) {          // function when you release the mouse button
+
     document.onmouseup = function(e) {          // функция при отпускании клавиши мыши
         document.onmousemove = null;              // when the key is released, no movement function
+
         document.onmousemove = null;              // когда клавиша отпущена - функции перемещения нету
 
         count = true;
 
         count = true;
 
     };
 
     };
  
     function mouseMove(e) {                    // function when you move the mouse, it works only while holding LKM
+
     function mouseMove(e) {                    // функция при перемещении мыши, работает только с зажатой ЛКМ
         var m = mouseCoords(e);                // we get estimated coordinates of the mouse cursor
+
         var m = mouseCoords(e);                // получаем расчетные координаты курсора мыши
 
         rect.x = m.x + rect.xPlus;
 
         rect.x = m.x + rect.xPlus;
//        v = 6.0 * (m.x - mx_) / dt / fps;    // inertia preservation
+
//        v = 6.0 * (m.x - mx_) / dt / fps;    // сохранение инерции
 
         v = 0;
 
         v = 0;
 
         mx_ = m.x;
 
         mx_ = m.x;
 
     }
 
     }
  
     function mouseCoords(e) {                  // function returns the calculated coordinates of the mouse cursor
+
     function mouseCoords(e) {                  // функция возвращает расчетные координаты курсора мыши
 
         var m = [];
 
         var m = [];
 
         var rect = canvas.getBoundingClientRect();
 
         var rect = canvas.getBoundingClientRect();
Line 144: Line 145:
 
     }
 
     }
  
     // plot
+
     // график
     var vGraph = new TM_graph(                  // determine the plot
+
     var vGraph = new TM_graph(                  // определить график
         "#vGraph",                              // on html-element #vGraph
+
         "#vGraph",                              // на html-элементе #vGraph
         250,                                    // the number of steps by "x" axis
+
         250,                                    // сколько шагов по оси "x" отображается
         -1, 1, 0.2);                            // min value of Y-axis, max value of Y-axis, Y-axis step
+
         -1, 1, 0.2);                            // мин. значение оси Y, макс. значение оси Y, шаг по оси Y
  
 
     function control() {
 
     function control() {
Line 156: Line 157:
 
     }
 
     }
 
     control();
 
     control();
//    setInterval(control, 1000 / fps);                      // start of the system
+
//    setInterval(control, 1000 / fps);                      // Запуск системы
  
 
     function calculate() {
 
     function calculate() {
Line 162: Line 163:
 
         for (var s=1; s<=spf; s++) {
 
         for (var s=1; s<=spf; s++) {
 
             var f = -B*v - C * (rect.x - x0) - C1*Math.pow(rect.x - x0,3)+2*F*Math.sin(t);
 
             var f = -B*v - C * (rect.x - x0) - C1*Math.pow(rect.x - x0,3)+2*F*Math.sin(t);
v += f / m * dt;
+
                        v += f / m * dt;
//console.log(f);
+
                        //console.log(f);
 
             rect.x += v * dt;
 
             rect.x += v * dt;
t+= dt;
+
                        t+= dt;
 
             steps++;
 
             steps++;
             if (steps % 80 == 0) vGraph.graphIter(steps, (rect.x-x0)/canvas.width*2);  // infeed graph data
+
             if (steps % 80 == 0) vGraph.graphIter(steps, (rect.x-x0)/canvas.width*2);  // подать данные на график
 
         }
 
         }
  
Line 174: Line 175:
 
     function draw() {
 
     function draw() {
 
         ctx.clearRect(0, 0, w, h);
 
         ctx.clearRect(0, 0, w, h);
draw_spring(startX, rect.x, h/2, 10, 50);
+
                draw_spring(startX, rect.x, h/2, 10, 50);
 
         ctx.fillStyle = "#0000ff";
 
         ctx.fillStyle = "#0000ff";
 
         ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
 
         ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
Line 180: Line 181:
  
  
function draw_spring(x_start, x_end, y, n, h) {
+
        function draw_spring(x_start, x_end, y, n, h) {
    ctx.lineWidth = 2;
+
            ctx.lineWidth = 2;
 
         ctx.strokeStyle = "#7394cb";
 
         ctx.strokeStyle = "#7394cb";
var L = x_end - x_start;
+
                var L = x_end - x_start;
for (var i = 0; i < n; i++) {
+
                for (var i = 0; i < n; i++) {
var x_st = x_start + L / n * i;
+
                        var x_st = x_start + L / n * i;
var x_end = x_start + L / n * (i + 1);
+
                        var x_end = x_start + L / n * (i + 1);
var l = x_end - x_st;
+
                        var l = x_end - x_st;
ctx.beginPath();
+
                        ctx.beginPath();
ctx.bezierCurveTo(x_st, y, x_st + l / 4, y + h, x_st + l / 2, y);
+
                        ctx.bezierCurveTo(x_st, y, x_st + l / 4, y + h, x_st + l / 2, y);
ctx.bezierCurveTo(x_st + l / 2, y, x_st + 3 * l / 4, y - h, x_st + l, y);
+
                        ctx.bezierCurveTo(x_st + l / 2, y, x_st + 3 * l / 4, y - h, x_st + l, y);
ctx.stroke();
+
                        ctx.stroke();
}
+
                }
}
+
        }
 
}
 
}

Revision as of 15:27, 6 June 2016

thumb|Нелинейный колебания груза с вынуждающей силой|500px

Annotation to the project

This project gives an idea about nonlinear oscillation of the load with the periodic force acting on it.

Formulation of the problem

Let’s put that the load on nonlinear spring has mass m and experiencing the action of an external force F, which has a law F = sin (t).

  • Task: formulate the problem on JavaScript which modulate motion of the load with different parameters of the system.

Overview

If the periodically changing of the external force is acting on the system, the system performs oscillations which repeat the pattern of changes of this force. Such oscillations are called forced.

F0 is the force amplitude and the greatest value of the force.

Because of the work of an external force, the maximum value of the potential energy of the spring and the kinetic energy of the load increase. This will increase the loss on overcome the resistance forces. In the end the work of the external force will exactly offset the energy losses in the system. Further growth of the oscillations in the system will stop and oscillations will be established with a constant amplitude.
Характер амплитуды

Equation of motion: [math]m\ddot x = -kx -{k_1}x^3 + {F_0}sin(t) - B \dot x[/math]

Visualization on JavaScript

Download program: SpringNoLine.rar

Text of the program on JavaScript (creator Киселев Павел):

File "Spring.js" <syntaxhighlight lang="javascript" enclose="div">

  window.addEventListener("load", Main_Spring, true);
   function Main_Spring() {
   var canvas = spring_canvas;
   canvas.onselectstart = function () {return false;};     // запрет выделения canvas
   var ctx = canvas.getContext("2d");                      // на ctx происходит рисование
   var w = canvas.width;                                   // ширина окна в расчетных координатах
   var h = canvas.height;                                  // высота окна в расчетных координатах
   var Pi = 3.1415926;                                     // число "пи"
   var m0 = 1;                                             // масштаб массы
   var T0 = 1;                                             // масштаб времени (период колебаний исходной системы)
   var t = 0;
   var k0 = 2 * Pi / T0;                                   // масштаб частоты
   var C0 = m0 * k0 * k0;                                  // масштаб жесткости
   var B0 = 2 * m0 * k0;                                   // масштаб вязкости
   var omega = 10;
   
   // *** Задание физических параметров ***
   var F = 80;
   var m = 1 * m0;                                         // масса
   var C = 1 * C0;                                         // жесткость
   var C1 = 1 * C0;                                        // жесткость1
   var B = .1 * B0;                                        // вязкость
   
   slider_m.value = (m / m0).toFixed(1); number_m.value = (m / m0).toFixed(1);
   slider_C.value = (C / C0).toFixed(1); number_C.value = (C / C0).toFixed(1);
   slider_C1.value = (C / C0).toFixed(1); number_C1.value = (C / C0).toFixed(1);
   slider_B.value = (B / B0).toFixed(1); number_B.value = (B / B0).toFixed(1);
   slider_F.value = (F / 40).toFixed(1); number_F.value = (F / 40).toFixed(1);
   // *** Задание вычислительных параметров ***
   var fps = 300;                                  // frames per second - число кадров в секунду (качечтво отображения)
   var spf = 100;                                  // steps per frame   - число шагов интегрирования между кадрами
   var dt  = 0.05 * T0 / fps;                      // шаг интегрирования (качество расчета)
   var steps = 0;                                  // количество шагов интегрирования
   function setM(new_m) {m = new_m * m0;}
   function setC(new_C) {C = new_C * C0;}
   function setC1(new_C1) {C1 = new_C1 * C0 * 0.067;}
   function setB(new_B) {B = new_B * B0;}
   function setF(new_F) {F = new_F * 40;}
   slider_m.oninput = function() {number_m.value = slider_m.value;       setM(slider_m.value);};
   number_m.oninput = function() {slider_m.value = number_m.value;       setM(number_m.value);};
   slider_C.oninput = function() {number_C.value = slider_C.value;       setC(slider_C.value);};
   number_C.oninput = function() {slider_C.value = number_C.value;       setC(number_C.value);};
   slider_C1.oninput = function() {number_C1.value = slider_C1.value;       setC1(slider_C1.value);};
   number_C1.oninput = function() {slider_C1.value = number_C1.value;       setC1(number_C1.value);};
   slider_B.oninput = function() {number_B.value = slider_B.value;       setB(slider_B.value);};
   number_B.oninput = function() {slider_B.value = number_B.value;       setB(number_B.value);};
   slider_F.oninput = function() {number_F.value = slider_F.value;       setF(slider_F.value);};
   number_F.oninput = function() {slider_F.value = number_F.value;       setF(number_F.value);};
   var count = true;                   // проводить ли расчет системы
   var v = 0;                          // скорость тела
   var rw = canvas.width / 30;         
   var rh = canvas.height / 1.5;
   var x0 = 15 * rw - rw / 2;          
   var y0 = rh / 1.33 - rh / 2;
   // параметры пружины
   var coil = 10;        // количество витков
   var startX = 0;       // закрепление пружины
   // создаем прямоугольник-грузик
   var rect = {
       x: x0,  width: rw,
       y: y0,  height: rh,
       fill: "rgba(0, 0, 255, 1)"      // цвет
   };
   // захват прямоугольника мышью
   var mx_;                                    // буфер позиции мыши (для расчета скорости при отпускании шара)
   document.onmousedown = function(e) {        // функция при нажатии клавиши мыши
       var m = mouseCoords(e);                 // получаем расчетные координаты курсора мыши
       var x = rect.x;
       var xw = rect.x + rect.width;
       var y = rect.y;
       var yh = rect.y + rect.height;
       if (x <= m.x && xw >= m.x   && y <= m.y && yh >= m.y) {
           if (e.which == 1) {                         // нажата левая клавиша мыши
               rect.xPlus = rect.x - m.x;              // сдвиг курсора относительно грузика по x
               rect.yPlus = rect.y - m.y;              // сдвиг курсора относительно грузика по y
               mx_ = m.x;
               count = false;
               document.onmousemove = mouseMove;       // пока клавиша нажата - работает функция перемещения
           }
       }
   };
   document.onmouseup = function(e) {          // функция при отпускании клавиши мыши
       document.onmousemove = null;              // когда клавиша отпущена - функции перемещения нету
       count = true;
   };
   function mouseMove(e) {                     // функция при перемещении мыши, работает только с зажатой ЛКМ
       var m = mouseCoords(e);                 // получаем расчетные координаты курсора мыши
       rect.x = m.x + rect.xPlus;

// v = 6.0 * (m.x - mx_) / dt / fps; // сохранение инерции

       v = 0;
       mx_ = m.x;
   }
   function mouseCoords(e) {                   // функция возвращает расчетные координаты курсора мыши
       var m = [];
       var rect = canvas.getBoundingClientRect();
       m.x = (e.clientX - rect.left);
       m.y = (e.clientY - rect.top);
       return m;
   }
   // график
   var vGraph = new TM_graph(                  // определить график
       "#vGraph",                              // на html-элементе #vGraph
       250,                                    // сколько шагов по оси "x" отображается
       -1, 1, 0.2);                            // мин. значение оси Y, макс. значение оси Y, шаг по оси Y
   function control() {
       calculate();
       draw();
       requestAnimationFrame(control);
   }
   control();

// setInterval(control, 1000 / fps); // Запуск системы

   function calculate() {
       if (!count) return;
       for (var s=1; s<=spf; s++) {
           var f = -B*v - C * (rect.x - x0) - C1*Math.pow(rect.x - x0,3)+2*F*Math.sin(t);
                       v += f / m * dt;
                       //console.log(f);
           rect.x += v * dt;
                       t+= dt;
           steps++;
           if (steps % 80 == 0) vGraph.graphIter(steps, (rect.x-x0)/canvas.width*2);   // подать данные на график
       }
   }
   function draw() {
       ctx.clearRect(0, 0, w, h);
               draw_spring(startX, rect.x, h/2, 10, 50);
       ctx.fillStyle = "#0000ff";
       ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
   }


       function draw_spring(x_start, x_end, y, n, h) {
           ctx.lineWidth = 2;
       ctx.strokeStyle = "#7394cb";
               var L = x_end - x_start;
               for (var i = 0; i < n; i++) {
                       var x_st = x_start + L / n * i;
                       var x_end = x_start + L / n * (i + 1);
                       var l = x_end - x_st;
                       ctx.beginPath();
                       ctx.bezierCurveTo(x_st, y, x_st + l / 4, y + h, x_st + l / 2, y);
                       ctx.bezierCurveTo(x_st + l / 2, y, x_st + 3 * l / 4, y - h, x_st + l, y);
                       ctx.stroke();
               }
       }
}