Driven oscillations of a mass on a nonlinear spring
thumb|Нелинейный колебания груза с вынуждающей силой|500px
Contents
Annotation to the project
This project gives an idea about nonlinear oscillation of cargo with the periodic force acting on it.
Formulation of the problem
Let’s put that the cargo 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 cargo with different parameters of the system.
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.
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 cargo 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:
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;}; // prohibition selection canvas var ctx = canvas.getContext("2d"); // at the ctx is drawing var w = canvas.width; // the width of the window in the calculated coordinates var h = canvas.height; // the height of the window in the calculated coordinates var Pi = 3.1415926; // Pi var m0 = 1; // weight scale var T0 = 1; // time scale (the period of oscillation of the original system) var t = 0; var k0 = 2 * Pi / T0; // frequency scale var C0 = m0 * k0 * k0; // hardness scale var B0 = 2 * m0 * k0; // viscosity scale var omega = 10; // *** Creating the physical parameters*** var F = 80; var m = 1 * m0; // weight var C = 1 * C0; // rigidity var C1 = 1 * C0; // rigidity1 var B = .1 * B0; // viscosity 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);
// *** Creating the parameters of computing ***
var fps = 300; // frames per second var spf = 100; // steps per frame var dt = 0.05 * T0 / fps; // integration step (calculation quality) var steps = 0; // the number of integration steps
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; // system analysis var v = 0; // cargo speed
var rw = canvas.width / 30; var rh = canvas.height / 1.5; var x0 = 15 * rw - rw / 2; var y0 = rh / 1.33 - rh / 2;
// spring settings var coil = 10; // number of turns var startX = 0; // spring fastening
// create a rectangle-cargo var rect = { x: x0, width: rw, y: y0, height: rh, fill: "rgba(0, 0, 255, 1)" // colour };
// capture a rectangle with the mouse var mx_; // буфер позиции мыши (для расчета скорости при отпускании шара) document.onmousedown = function(e) { // function by pressing the mouse button var m = mouseCoords(e); // we get estimated coordinates of the mouse cursor 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) { // left mouse button is pressed rect.xPlus = rect.x - m.x; // cursor shift relative to the cargo on the x rect.yPlus = rect.y - m.y; // cursor shift relative to the cargo on the y mx_ = m.x; count = false; document.onmousemove = mouseMove; // while a key is pressed, fanction of motions is correct } } };
document.onmouseup = function(e) { // function when you release the mouse button document.onmousemove = null; // when the key is released, no movement function count = true; };
function mouseMove(e) { // function when you move the mouse, it works only while holding LKM var m = mouseCoords(e); // we get estimated coordinates of the mouse cursor rect.x = m.x + rect.xPlus;
// v = 6.0 * (m.x - mx_) / dt / fps; // inertia preservation
v = 0; mx_ = m.x; }
function mouseCoords(e) { // function returns the calculated coordinates of the mouse cursor var m = []; var rect = canvas.getBoundingClientRect(); m.x = (e.clientX - rect.left); m.y = (e.clientY - rect.top); return m; }
// plot var vGraph = new TM_graph( // determine the plot "#vGraph", // on html-element #vGraph 250, // the number of steps by "x" axis -1, 1, 0.2); // min value of Y-axis, max value of Y-axis, Y-axis step
function control() { calculate(); draw(); requestAnimationFrame(control); } control();
// setInterval(control, 1000 / fps); // starting system
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); // infeed graph data }
}
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(); } }
}