|
|
Строка 1: |
Строка 1: |
− | [[Виртуальная лаборатория]] > [[Цепочка частиц с вращательными степенями свободы]] <HR>
| |
| | | |
− | == Краткое описание ==
| |
− |
| |
− | Рассматривается совокупность твердых тел, образующих цепочки. Центры масс фиксированы. Взаимодействия осуществляются посредством балок Бернулли-Эйлера, соединяющих тела.
| |
− |
| |
− | == Реализации цепочки ==
| |
− |
| |
− |
| |
− | <div class="mw-collapsible mw-collapsed" style="width:100%" >
| |
− |
| |
− | <div class="mw-collapsible-content">
| |
− | <syntaxhighlight lang="javascript" line start="1" enclose="div">
| |
− |
| |
− | window.addEventListener("load", MainSystem, true);
| |
− |
| |
− | function MainSystem(){
| |
− | var context_s = canvasSystem.getContext('2d');
| |
− | var context_g = canvasGraph.getContext('2d');
| |
− | var context_g_1 = canvasGraph_1.getContext('2d');
| |
− | var context_g_2 = canvasGraph_2.getContext('2d');
| |
− |
| |
− | const Pi = 3.1415926;
| |
− | const m0 = 1;
| |
− | const T0 = 1;
| |
− | const l0 = 1;
| |
− | const E0 = 1;
| |
− |
| |
− | //Width of canvas - width of browser
| |
− | const distance_between_canvases = 5; //5px
| |
− | canvasSystem.width = document.body.clientWidth;
| |
− | canvasGraph.width = document.body.clientWidth / 2 - distance_between_canvases;
| |
− | canvasGraph_1.width = document.body.clientWidth / 2 - distance_between_canvases;
| |
− | canvasGraph_2.width = document.body.clientWidth;
| |
− |
| |
− | /* -- Used constans -- */
| |
− | var Db = 0.1 * l0; // Diameter of beam
| |
− | const l = 30 * l0; //Length of beam
| |
− | const a = 60 * l0; //Length of object
| |
− | var Db2 = Db * Db;
| |
− | var J = Pi * Db2 * Db2 / 64; //Polar moment of inertia
| |
− | const E = 10000000 * E0; //Youngs modulus
| |
− | var C = E * J / l;
| |
− | var N = parseFloat(number_of_objects.value) + 1; //number_of_objects.value is number of objects
| |
− | const m = 0.01 * m0; //Mass of object
| |
− | const Q = m * a * a / 12; //Moment of inertia
| |
− | const w_c = Math.sqrt(2 * C / Q); //Self frequency
| |
− |
| |
− | const fps = 50; // frames per second
| |
− | var spf = calcul_speed.value; // steps per frame
| |
− | const frequency = 1000 / fps; //frequency of call function - 1000 milliseconds/ fps
| |
− | const dt = 0.05 * T0 / fps; //Step of integration
| |
− |
| |
− | var scale = canvasSystem.width / N; //Scale of graph of system
| |
− | var scale1 = canvasGraph_2.width / (N + 2); //Scale of graph of angels
| |
− |
| |
− | //For wave
| |
− | const n = 1; //Number of full-wave
| |
− | var k_ = 2 * Pi / (l * (N - 2) * n); //Spatial frequencyw
| |
− | var w_ = Math.sqrt((-2 * C / Q * l * l) * k_ * k_ + (12 * C / Q));
| |
− |
| |
− | /* -- Used variables -- */
| |
− | var K0 = 0; var P0 = 0; var E_p0 = 0; var L0 = 0; //Energies at i-step
| |
− | var K1 = 0; var P1 = 0; var E_p1 = 0; var L1 = 0; // Energies at (i+1)-step
| |
− | var E_m = 0; //Maximum of Energy at the first moment
| |
− | var t = 0; //Time
| |
− |
| |
− | var U = []; //Exact solution for wave
| |
− | var shaft = []; //Objects
| |
− |
| |
− | var pause = false;
| |
− | const stretch_graphics = 3;
| |
− | var help = stretch_graphics * canvasGraph.width; //Scale of graph of energies
| |
− | var firstCalculation = true;
| |
− | /* -- */
| |
− |
| |
− | //Restart the programm with new parameters
| |
− | restart.onclick = function(){
| |
− | N = parseFloat(number_of_objects.value) + 1;
| |
− | scale = canvasSystem.width / N;
| |
− | scale1 = canvasGraph_2.width / (N + 2);
| |
− | spf = calcul_speed.value;
| |
− | J = Pi * Db2 * Db2 / 64;
| |
− | C = E * J / l;
| |
− |
| |
− | context_s.clearRect(0, 0, canvasSystem.width, canvasSystem.height);
| |
− | context_g.clearRect(0, 0, canvasGraph.width, canvasGraph.height);
| |
− | context_g_1.clearRect(0, 0, canvasGraph_1.width, canvasGraph_1.height);
| |
− | context_g_2.clearRect(0, 0, canvasGraph_2.width, canvasGraph_2.height);
| |
− |
| |
− | shaft = [];
| |
− | addSystem(shaft);
| |
− |
| |
− | firstCalculation = true;
| |
− | t = 0;
| |
− | P1 = 0;
| |
− | K1 = 0;
| |
− | E_m = 0;
| |
− | }
| |
− |
| |
− | //Pause
| |
− | pause_button.onclick = function(){
| |
− | pause = !pause;
| |
− | if(pause == false)
| |
− | pause_button.value = "Pause";
| |
− | else
| |
− | pause_button.value = "Run";
| |
− | }
| |
− |
| |
− | //Calculate all parameters of system
| |
− | function control(){
| |
− | if(!pause){
| |
− | /* -- Find the maximum of energy -- */
| |
− | if(firstCalculation){
| |
− | for (var i = 1; i < N; i++){
| |
− | E_m += Q * shaft[i].w * shaft[i].w / 2;
| |
− | }
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | E_m += C / 2 * (12 * shaft[i].fi * shaft[i].fi - ((shaft[i-1].fi - shaft[i].fi) * (shaft[i-1].fi - shaft[i].fi) +
| |
− | (shaft[i].fi - shaft[i+1].fi) * (shaft[i].fi - shaft[i+1].fi)));
| |
− | }
| |
− |
| |
− | L0 = E_m;
| |
− | E_p0 = E_m / 2;
| |
− | firstCalculation = false;
| |
− | }
| |
− | /* -- */
| |
− |
| |
− | physics();
| |
− | draw();
| |
− |
| |
− | if(t*help > canvasGraph.width){
| |
− | t = 0;
| |
− | context_g.clearRect(0, 0, canvasGraph.width, canvasGraph.height);
| |
− | context_g_1.clearRect(0, 0, canvasGraph_1.width, canvasGraph_1.height);
| |
− | }
| |
− |
| |
− | draw_Graph_energy(t*help, (t + dt)*help);
| |
− | draw_Graph_angels();
| |
− |
| |
− | //exact_solution_for_wave(t*help);
| |
− |
| |
− | P0 = P1;
| |
− | K0 = K1;
| |
− | L0 = L1;
| |
− | E_p0 = E_p1;
| |
− | E_p1 = 0;
| |
− | L1 = 0;
| |
− | P1 = 0;
| |
− | K1 = 0;
| |
− | t += dt;
| |
− | }
| |
− | }
| |
− |
| |
− | //Physics - calculate the positions of objects
| |
− | function physics(){
| |
− | for (var s = 1; s <= spf; s++){
| |
− | //Periodic initial conditions
| |
− | shaft[0].fi = shaft[N-1].fi;
| |
− | shaft[N].fi = shaft[1].fi;
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | shaft[i].M = - 2 * C * (shaft[i-1].fi + 2 * shaft[i].fi) - 2 * C * (2 * shaft[i].fi + shaft[i+1].fi);
| |
− | }
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | shaft[i].w += shaft[i].M / Q * dt;
| |
− | shaft[i].fi += shaft[i].w * dt;
| |
− | }
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | shaft[i].M = 0;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | //Draw the graph of system
| |
− | function draw(){
| |
− | context_s.clearRect(0, 0, canvasSystem.width, canvasSystem.height);
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | context_s.beginPath();
| |
− | context_s.moveTo(shaft[i].x - (a/2) * Math.sin(shaft[i].fi), shaft[i].y - (a/2) * Math.cos(shaft[i].fi));
| |
− | context_s.lineTo(shaft[i].x + (a/2) * Math.sin(shaft[i].fi), shaft[i].y + (a/2) * Math.cos(shaft[i].fi));
| |
− | context_s.closePath();
| |
− | context_s.stroke();
| |
− | }
| |
− | }
| |
− |
| |
− | //Draw the graph of angels
| |
− | function draw_Graph_angels(){
| |
− | context_g_2.clearRect(0, 0, canvasGraph_2.width, canvasGraph_2.height);
| |
− |
| |
− | for(var i = 0; i < N; i++){
| |
− | context_g_2.beginPath();
| |
− | context_g_2.moveTo(scale1 * (i+1), -shaft[i].fi / (Pi/2) * canvasGraph_2.height / 2 + canvasGraph_2.height / 2);
| |
− | context_g_2.lineTo(scale1 * (i+2), -shaft[i+1].fi / (Pi/2) * canvasGraph_2.height / 2 + canvasGraph_2.height / 2);
| |
− | context_g_2.closePath();
| |
− | context_g_2.stroke();
| |
− | }
| |
− | }
| |
− |
| |
− | //Draw the graphics of energies
| |
− | function draw_Graph_energy(x0, x1){
| |
− | //Potential
| |
− | context_g_1.beginPath();
| |
− | context_g_1.strokeStyle = "#FF0000";
| |
− | context_g_1.moveTo(x0, -P0 / E_m * canvasGraph_1.height + canvasGraph_1.height);
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | P1 += C / 2 * (12 * shaft[i].fi * shaft[i].fi - ((shaft[i-1].fi - shaft[i].fi) * (shaft[i-1].fi - shaft[i].fi) +
| |
− | (shaft[i].fi - shaft[i+1].fi) * (shaft[i].fi - shaft[i+1].fi)));
| |
− | }
| |
− |
| |
− | context_g_1.lineTo(x1, -P1 / E_m * canvasGraph_1.height + canvasGraph_1.height);
| |
− | context_g_1.closePath();
| |
− | context_g_1.stroke();
| |
− |
| |
− | //Kinetical
| |
− | context_g_1.beginPath();
| |
− | context_g_1.strokeStyle = "#000000";
| |
− | context_g_1.moveTo(x0, -K0 / E_m * canvasGraph_1.height + canvasGraph_1.height);
| |
− |
| |
− | for (var i = 1; i < N; i++){
| |
− | K1 += Q * shaft[i].w * shaft[i].w / 2;
| |
− | }
| |
− |
| |
− | context_g_1.lineTo(x1, -K1 / E_m * canvasGraph_1.height + canvasGraph_1.height);
| |
− | context_g_1.closePath();
| |
− | context_g_1.stroke();
| |
− |
| |
− | //Full energy
| |
− | context_g_1.beginPath();
| |
− | context_g_1.strokeStyle = "blue";
| |
− | context_g_1.moveTo(x0, -E_p0 / E_m * canvasGraph.height + canvasGraph.height);
| |
− |
| |
− | E_p1 = (K1 + P1) / 2;
| |
− |
| |
− | context_g_1.lineTo(x1, -E_p1 / E_m * canvasGraph.height + canvasGraph.height);
| |
− | context_g_1.closePath();
| |
− | context_g_1.stroke();
| |
− |
| |
− | //Lagrangian
| |
− | context_g.beginPath();
| |
− | context_g.strokeStyle = "orange";
| |
− | context_g.moveTo(x0, -L0 / E_m * canvasGraph.height / 2 + canvasGraph.height / 2);
| |
− |
| |
− | L1 = K1 - P1;
| |
− |
| |
− | context_g.lineTo(x1, -L1 / E_m * canvasGraph.height / 2 + canvasGraph.height / 2);
| |
− | context_g.closePath();
| |
− | context_g.stroke();
| |
− | }
| |
− |
| |
− | //Add the system of objects
| |
− | function addSystem(shaft){
| |
− | for (var i = 0; i < N + 1; i++){
| |
− | var shaft_new = [];
| |
− |
| |
− | shaft_new.x = scale * i;
| |
− | shaft_new.y = canvasSystem.height / 2;
| |
− | shaft_new.fi = 0;
| |
− | shaft_new.w = 0;
| |
− | shaft_new.M = 0;
| |
− | shaft[shaft.length] = shaft_new;
| |
− | }
| |
− |
| |
− | /* --Initial conditions-- */
| |
− | //Random velocities
| |
− | if(all_.checked){
| |
− | var average_w = 0; //Average velocity
| |
− |
| |
− | for (var i = 0; i < N; i++){
| |
− | shaft[i].w = Math.random() * w_c;
| |
− | average_w += shaft[i].w;
| |
− | }
| |
− |
| |
− | average_w /= N;
| |
− |
| |
− | for (var i = 0; i < N; i++){
| |
− | shaft[i].w -= average_w;
| |
− | }
| |
− | }
| |
− |
| |
− | // N/10 - Central part of objects by sin
| |
− | if(part.checked){
| |
− | for (var i = Math.floor(-Math.floor(N / 10) / 2); i < Math.floor(Math.floor(N / 10) / 2); i++){
| |
− | shaft[Math.floor(N / 2) + i + 1].fi =
| |
− | Math.sin(2 * Pi * (Math.floor(Math.floor(N / 10) / 2) - i) * (Math.floor(Math.floor(N / 10) / 2) + i) / N/2);
| |
− | }
| |
− | }
| |
− |
| |
− | //Central object
| |
− | if(one.checked){
| |
− | shaft[Math.floor(N / 2)].w = w_c;
| |
− | }
| |
− |
| |
− | //Wave
| |
− | if(wave.checked){
| |
− | for (var i = 1; i < N; i++){
| |
− | shaft[i].fi = Math.sin(k_ * (l * i));
| |
− | shaft[i].w = -w_ * Math.cos(k_ * (l * i));
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | //Exact solution for wave
| |
− | function exact_solution_for_wave(t) {
| |
− | for (var i = 1; i < N; i++){
| |
− | U[i] = Math.sin(k_ * (l * i) - w_ * t / 200);
| |
− | }
| |
− | //context_g_2.clearRect(0, 0, canvasGraph_2.width, canvasGraph_2.height);
| |
− | for(var i = 0; i < N; i++){
| |
− | context_g_2.beginPath();
| |
− | context_g_2.moveTo(scale1 * (i+1), -U[i] / (Pi/2) * canvasGraph_2.height / 2 + canvasGraph_2.height / 2);
| |
− | context_g_2.lineTo(scale1 * (i+2), -U[i+1] / (Pi/2) * canvasGraph_2.height / 2 + canvasGraph_2.height / 2);
| |
− | context_g_2.closePath();
| |
− | context_g_2.stroke();
| |
− | }
| |
− | }
| |
− |
| |
− | addSystem(shaft); //Adding our system of objects
| |
− |
| |
− | setInterval(control, frequency);
| |
− | }
| |
− | </syntaxhighlight>
| |
− |
| |
− | <syntaxhighlight lang="html5" line start="1" enclose="div">
| |
− | <!DOCTYPE html>
| |
− | <html>
| |
− | <body>
| |
− | <canvas id="canvasSystem" width="1200" height="300" style="border:1px solid #000000;"></canvas><br><br>
| |
− |
| |
− | Number of objects: <input type="number" id="number_of_objects" value="500" step=1 style="width: 5em">,
| |
− | Calculation speed: <input type="range" id="calcul_speed" value="100" step=0.01 min=10 max=300><br>
| |
− |
| |
− | Initial conditions:<br>
| |
− | <input type="radio" checked="checked" name="initial_conditions" id="all_"/>Random velocities<br>
| |
− | <input type="radio" name="initial_conditions" id="part"/>Central part of objects by sin<br>
| |
− | <input type="radio" name="initial_conditions" id="one"/>One object<br>
| |
− | <input type="radio" name="initial_conditions" id="wave"/>Wave<br>
| |
− | <input type="button" id="restart" value="Restart">
| |
− | <input type="button" id="pause_button" value="Pause"><br><br>
| |
− |
| |
− | Graphics:<br>
| |
− | <canvas id="canvasGraph" width="600" height="300" style="border:1px solid #000000;"></canvas>
| |
− | <canvas id="canvasGraph_1" width="600" height="300" style="border:1px solid #000000;"></canvas><br>
| |
− | L<hr align="left" width="50" size="3" color="orange" />
| |
− | E / 2<hr align="left" width="50" size="3" color="blue" />
| |
− | K<hr align="left" width="50" size="3" color="#000000" />
| |
− | P<hr align="left" width="50" size="3" color="#FF0000" /><br>
| |
− |
| |
− | Angles:<br>
| |
− | <canvas id="canvasGraph_2" width="1200" height="300" style="border:1px solid #000000;"></canvas><br>
| |
− |
| |
− | <script src="simulation.js"></script>
| |
− | </body>
| |
− | </html>
| |
− | </syntaxhighlight>
| |
− | </div>
| |
− | </div>
| |
− | [https://bitbucket.org/GA__GA/spin-degree-of-freedom/get/c518f9b3fb9b.zip Скачать архив]
| |
− | '''Текст программы на языке JavaScript (разработчик [[Александров Александр]]):'''
| |