Редактирование: Цепочка из частиц с вращательными степенями свободы
Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.
Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия | Ваш текст | ||
Строка 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; | ||
+ | |||
+ | //ширина канваса - ширина окна в браузере | ||
+ | const distance_between_canvases = 5; | ||
+ | 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; | ||
+ | |||
+ | var Db = parseFloat(diameter.value) * l0; // диаметр балки | ||
+ | const l = 60 * l0; // длина балки | ||
+ | const a = 60 * l0; // длина стержня | ||
+ | var Db2 = Db * Db; | ||
+ | var J = Pi * Db2 * Db2 / 64; // коэффициент жесткости | ||
+ | const E = 10000000 * E0; // модуль Юнга | ||
+ | var C = E * J / l; | ||
+ | var N = parseFloat(number_of_objects.value) + 1; //число объектов | ||
+ | const m = 0.01 * m0; // масса | ||
+ | const Q = m * l * l / 12; // момент инерции стержня | ||
+ | const w_c = Math.sqrt(2 * C / Q); // собственная частота колебаний | ||
+ | |||
+ | //Изменение системы | ||
+ | restart.onclick = function() | ||
+ | { | ||
+ | N = parseFloat(number_of_objects.value) + 1; //новое кол-во тел | ||
+ | scale = canvasSystem.width / N; | ||
+ | spf = calcul_speed.value; | ||
+ | Db = parseFloat(diameter.value) * l0; //новый диаметр балки | ||
+ | Db2 = Db * Db; | ||
+ | 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); | ||
+ | |||
+ | t = 0; | ||
+ | P1 = 0; | ||
+ | K1 = 0; | ||
+ | }; | ||
+ | |||
+ | const fps = 50; // frames per second (качество отображения) | ||
+ | var spf = calcul_speed.value; // steps per frame (скорость расчёта) | ||
+ | const frequency = 1000 / fps; //Время, через которые будет выполнятся код - 1000 миллисекунд / fps | ||
+ | const dt = 0.05 * T0 / fps; | ||
+ | |||
+ | var scale = canvasSystem.width / N; // Для масштабирования | ||
+ | |||
+ | var K0 = 0; var P0 = 0; var E_p0 = 0; var L0; // показания энергий на i-шаге | ||
+ | var K1 = 0; var P1 = 0; var E_p1 = 0; var L1; // показания энергий на (i+1)-шаге | ||
+ | var K_m; //максимальное значение энергии в начальный момент времени - для масштабирования | ||
+ | var t = 0; // время | ||
+ | |||
+ | //Пауза | ||
+ | pause_button.onclick = function() | ||
+ | { | ||
+ | pause = !pause; | ||
+ | if(pause == false) | ||
+ | pause_button.value = "Pause"; | ||
+ | else | ||
+ | pause_button.value = "Run"; | ||
+ | } | ||
+ | |||
+ | var pause = false; | ||
+ | const stretch_graphics = 3; | ||
+ | var help = stretch_graphics * canvasGraph.width; //масштабирование графиков по оси t | ||
+ | |||
+ | // Запуск вычислений | ||
+ | function control() | ||
+ | { | ||
+ | if(!pause) | ||
+ | { | ||
+ | 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(); | ||
+ | |||
+ | P0 = P1; | ||
+ | K0 = K1; | ||
+ | L0 = L1; | ||
+ | E_p0 = E_p1; | ||
+ | E_p1 = 0; | ||
+ | L1 = 0; | ||
+ | P1 = 0; | ||
+ | K1 = 0; | ||
+ | t += dt; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //Физика - вычисление новых положений | ||
+ | function physics() | ||
+ | { | ||
+ | for (var s = 1; s <= spf; s++) | ||
+ | { | ||
+ | shaft[0].v = shaft[N-1].v; | ||
+ | shaft[N].v = shaft[1].v; | ||
+ | |||
+ | for (var i = 1; i < N; i++) | ||
+ | { | ||
+ | shaft[i].M = - 2 * C * (shaft[i-1].v + 2 * shaft[i].v) - 2 * C * (2 * shaft[i].v + shaft[i+1].v); | ||
+ | } | ||
+ | |||
+ | for (var i = 1; i < N; i++) | ||
+ | { | ||
+ | shaft[i].w += shaft[i].M / Q * dt; | ||
+ | shaft[i].v += shaft[i].w * dt; | ||
+ | } | ||
+ | |||
+ | for (var i = 1; i < N; i++) | ||
+ | { | ||
+ | shaft[i].M = 0; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //Отрисовка системы | ||
+ | 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].v), shaft[i].y - (a/2) * Math.cos(shaft[i].v)); | ||
+ | context_s.lineTo(shaft[i].x + (a/2) * Math.sin(shaft[i].v), shaft[i].y + (a/2) * Math.cos(shaft[i].v)); | ||
+ | context_s.closePath(); | ||
+ | context_s.stroke(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // График углов | ||
+ | function draw_Graph_angels() | ||
+ | { | ||
+ | var scale1 = canvasGraph_2.width / (N + 2); | ||
+ | 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].v / (Pi/2) * canvasGraph_2.height / 2 + canvasGraph_2.height / 2); | ||
+ | context_g_2.lineTo(scale1 * (i+2), -shaft[i+1].v / (Pi/2) * canvasGraph_2.height / 2 + canvasGraph_2.height / 2); | ||
+ | context_g_2.closePath(); | ||
+ | context_g_2.stroke(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Графики энергий | ||
+ | function draw_Graph_energy(x0, x1) | ||
+ | { | ||
+ | //потенциальная | ||
+ | context_g_1.beginPath(); | ||
+ | context_g_1.strokeStyle = "#FF0000"; | ||
+ | context_g_1.moveTo(x0, -P0 / K_m * canvasGraph_1.height + canvasGraph_1.height); | ||
+ | |||
+ | for (var i = 1; i < N; i++) | ||
+ | { | ||
+ | P1 += C / 2 * (12 * shaft[i].v * shaft[i].v - ((shaft[i-1].v - shaft[i].v) * (shaft[i-1].v - shaft[i].v) + | ||
+ | (shaft[i].v - shaft[i+1].v) * (shaft[i].v - shaft[i+1].v))); | ||
+ | } | ||
+ | |||
+ | context_g_1.lineTo(x1, -P1 / K_m * canvasGraph_1.height + canvasGraph_1.height); | ||
+ | context_g_1.closePath(); | ||
+ | context_g_1.stroke(); | ||
+ | |||
+ | //кинетическая | ||
+ | context_g_1.beginPath(); | ||
+ | context_g_1.strokeStyle = "#000000"; | ||
+ | context_g_1.moveTo(x0, -K0 / K_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 / K_m * canvasGraph_1.height + canvasGraph_1.height); | ||
+ | context_g_1.closePath(); | ||
+ | context_g_1.stroke(); | ||
+ | |||
+ | //полная | ||
+ | context_g_1.beginPath(); | ||
+ | context_g_1.strokeStyle = "blue"; | ||
+ | context_g_1.moveTo(x0, -E_p0 / K_m * canvasGraph.height + canvasGraph.height); | ||
+ | |||
+ | E_p1 = K1 + P1; | ||
+ | |||
+ | context_g_1.lineTo(x1, -E_p1 / K_m * canvasGraph.height + canvasGraph.height); | ||
+ | context_g_1.closePath(); | ||
+ | context_g_1.stroke(); | ||
+ | |||
+ | //Лагранжиан | ||
+ | context_g.beginPath(); | ||
+ | context_g.strokeStyle = "orange"; | ||
+ | context_g.moveTo(x0, -L0 / K_m * canvasGraph.height / 2 + canvasGraph.height / 2); | ||
+ | |||
+ | L1 = K1 - P1; | ||
+ | |||
+ | context_g.lineTo(x1, -L1 / K_m * canvasGraph.height / 2 + canvasGraph.height / 2); | ||
+ | context_g.closePath(); | ||
+ | context_g.stroke(); | ||
+ | } | ||
+ | |||
+ | // Добавление системы из объектов | ||
+ | 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.v = 0; | ||
+ | shaft_new.w = 0; | ||
+ | shaft_new.M = 0; | ||
+ | shaft[shaft.length] = shaft_new; | ||
+ | } | ||
+ | |||
+ | K_m = 0; | ||
+ | var average_w = 0; // средняя скорость объектов | ||
+ | // Задаем начальные условия | ||
+ | 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; | ||
+ | K_m += Q * shaft[i].w * shaft[i].w / 2; | ||
+ | } | ||
+ | |||
+ | E_p0 = K_m; | ||
+ | L0 = K_m; | ||
+ | } | ||
+ | |||
+ | shaft = []; | ||
+ | addSystem(shaft); //Добавление системы стержней | ||
+ | |||
+ | setInterval(control, frequency); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang="html5" line start="1" enclose="div"> | ||
+ | |||
+ | <!DOCTYPE html> | ||
+ | <html> | ||
+ | <head> | ||
+ | </head> | ||
+ | <body> | ||
+ | <br> | ||
+ | <!-- ќбласть дл¤ рисовани¤ системы --> | ||
+ | <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"> | ||
+ | Diameter of beam: <input type="number" id="diameter" value="0.1" step=0.01 style="width: 5em">c.u.<br> | ||
+ | Calculation speed: <input type="range" id="calcul_speed" value="100" step=0.01 min=10 max=300> | ||
+ | <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<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/1a3d8ed057cd.zip]] | ||
+ | '''Текст программы на языке JavaScript (разработчик [[Александров Александр]]):''' |