Текущая версия |
Ваш текст |
Строка 1: |
Строка 1: |
− | [[en:Energy fluctuations in one-dimensional crystal]]
| + | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Tcvetkov/Bessel_fluctuations/Bessel_fluctuations_v2.3_no_realiz/Bessel_fluctuations.html |width=1030 |height=640 |border=0 }} |
− | [[ТМ|Кафедра ТМ]] > [[Проект "Термокристалл"]] > [[Колебания энергий в одномерном кристалле]] <HR>
| |
− | [[Виртуальная лаборатория]] > [[Колебания энергий в одномерном кристалле]] <HR>
| |
− | [[Д.В. Цветков]] (программирование), [[А.М. Кривцов]] (аналитическое решение) <HR>
| |
− | | |
− | Данная программа демонстрирует колебания кинетической, потенциальной и полной энергий в одномерном кристалле.
| |
− | Колебания кинетической энергии описываются следующим уравнением:
| |
− | | |
− | :<math>
| |
− | K_J(t) = \frac{E}{2} \left(1 + J_0(4 \omega_0 )\right)
| |
− | ,\qquad \omega_0 = \sqrt{C/m},
| |
− | </math>
| |
− | где
| |
− | <math>J_0</math> — Функция Бесселя первого рода в точке 0,
| |
− | <math>C</math> — жесткость связи между частицами,
| |
− | <math>m</math> — масса частицы.
| |
− | | |
− | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Tcvetkov/Bessel_fluctuations/Bessel_fluctuations_v3.0/Bessel_fluctuations.html |width=1055 |height=675 |border=0 }} | |
− | | |
− | Скачать программу: [[Медиа:Bessel_fluctuations_v3.0.zip|Bessel_fluctuations_v3.0.zip]]
| |
− | <div class="mw-collapsible mw-collapsed" style="width:100%" >
| |
− | '''Текст программы на языке JavaScript (использована библиотека [https://github.com/SheetJS/bessel bessel.js]):''' <div class="mw-collapsible-content">
| |
− | Файл '''"Bessel_fluctuations.js"'''
| |
− | <syntaxhighlight lang="javascript" line start="1" enclose="div">
| |
− | window.addEventListener("load", main_BF, false);
| |
− | function main_BF() {
| |
− | | |
− | // Предварительные установки
| |
− | var a0 = 1; // масштаб расстояния
| |
− | var t0 = 1; // масштаб времени
| |
− | var m0 = 1; // масштаб массы
| |
− | | |
− | var k0 = 2 * Math.PI / t0; // масштаб частоты
| |
− | var C0 = m0 * k0 * k0; // масштаб жесткости
| |
− | | |
− | var m = 1 * m0; // масса
| |
− | var C = 0.02 * C0; // жесткость
| |
− | | |
− | var dx = 1 * a0; // шаг сетки по оси x
| |
− | var dt = 0.02 * t0; // шаг интегрирования по времени
| |
− | | |
− | var R = 10; // количество реализаций
| |
− | var N = 10000; // количество частиц в каждой реализации
| |
− | var periods = 10; // время расчета в периодах колебаний энергий
| |
− | | |
− | var koeff = C / (dx * dx) / m * dt; // коэффициент для уравнения динамики частиц
| |
− | | |
− | var T;
| |
− | // функция переводит время в периодах в расчетное время
| |
− | function set_periods(n) {
| |
− | // первый раз кинетическая и потенциальная энергии доходят до нуля за 0.4 периода колебаний
| |
− | var T0 = Math.PI / (Math.sqrt(C / m)) / 2; // период колебаний
| |
− | if (n >= 0.4 * T0) T = T0 * ( 0.4 + 0.75 + (n - 1) );
| |
− | else T = n;
| |
− | }
| |
− | set_periods(periods);
| |
− | | |
− | // интерфейс программы
| |
− | N_number.value = N;
| |
− | N_number.oninput = function() {N = parseInt(N_number.value);};
| |
− | periods_number.value = periods;
| |
− | periods_number.oninput = function() {
| |
− | set_periods(parseFloat(periods_number.value));
| |
− | };
| |
− | R_number.value = R;
| |
− | R_number.oninput = function() {R = parseInt(R_number.value);};
| |
− | button_start.onclick = calculate_new_system;
| |
− | button_stop.onclick = function() {
| |
− | working = false;
| |
− | };
| |
− | checkbox_Bessel.onchange = function() {
| |
− | draw();
| |
− | if (checkbox_Bessel.checked) div_txt_J0.style.display = "block";
| |
− | else div_txt_J0.style.display = "none"
| |
− | };
| |
− | checkbox_K.onchange = function() {
| |
− | draw();
| |
− | if (checkbox_K.checked) div_txt_K.style.display = "block";
| |
− | else div_txt_K.style.display = "none"
| |
− | };
| |
− | checkbox_P.onchange = function() {
| |
− | draw();
| |
− | if (checkbox_P.checked) div_txt_P.style.display = "block";
| |
− | else div_txt_P.style.display = "none"
| |
− | };
| |
− | checkbox_E.onchange = function() {
| |
− | draw();
| |
− | if (checkbox_E.checked) div_txt_E.style.display = "block";
| |
− | else div_txt_E.style.display = "none"
| |
− | };
| |
− | | |
− | var ctx = BF_canvas.getContext("2d"); // на context происходит рисование
| |
− | var w = BF_canvas.width; // ширина окна в расчетных координатах
| |
− | var h = BF_canvas.height; // высота окна в расчетных координатах
| |
− | | |
− | // основная расчетная функция
| |
− | var data_K, data_P, data_E; // данные для графика
| |
− | var t, n;
| |
− | var t_start;
| |
− | var working;
| |
− | var step;
| |
− | function calculate_new_system() {
| |
− | t = 0;
| |
− | n = N + 2; // количество узлов по оси x + 2 для ГУ
| |
− | working = true;
| |
− | step = 0;
| |
− | | |
− | span_time_calc.innerHTML = "";
| |
− | div_calc_speed.style.display = "none";
| |
− | button_start.style.display = "none";
| |
− | button_stop.style.display = "inline";
| |
− | | |
− | // задание начальных условий
| |
− | var all_P = [];
| |
− | for (var r = 0; r < R; r++) {
| |
− | var P = [];
| |
− | for (var i = 1; i < n - 1; i++) {
| |
− | P[i] = {};
| |
− | P[i].u = 0;
| |
− | P[i].v = (2 * Math.random() - 1) * 0.25;
| |
− | }
| |
− | // периодические граничные условия
| |
− | P[0] = P[n - 2];
| |
− | P[n - 1] = P[1];
| |
− | all_P.push(P);
| |
− | }
| |
− | | |
− | data_K = []; data_P = []; data_E = [];
| |
− | | |
− | // основной расчет
| |
− | t_start = performance.now();
| |
− | calculate(all_P);
| |
− | }
| |
− | calculate_new_system();
| |
− | | |
− | function calculate(all_P) {
| |
− | var t1 = performance.now();
| |
− | while (t < T) {
| |
− | // расчет энергий для графиков
| |
− | var Kin = 0;
| |
− | var Pot = 0;
| |
− | for (var p = 0; p < all_P.length; p++) {
| |
− | var P = all_P[p];
| |
− | for (var j = 1; j < n - 1; j++) {Kin += P[j].v * P[j].v;}
| |
− | for (var j = 1; j < n - 1; j++) {Pot += Math.pow(P[j].u - P[j - 1].u, 2);}
| |
− | }
| |
− | Kin = Kin * m / all_P.length;
| |
− | Pot = Pot * C / all_P.length;
| |
− | data_K.push(Kin);
| |
− | data_P.push(Pot);
| |
− | data_E.push(Kin + Pot);
| |
− | | |
− | // расчет состояния системы на следующем шаге
| |
− | for (var p = 0; p < all_P.length; p++) {
| |
− | var P = all_P[p];
| |
− | for (var i = 1; i < n - 1; i++) {
| |
− | P[i].v += (P[i + 1].u - 2 * P[i].u + P[i - 1].u) * koeff;
| |
− | }
| |
− | for (var i = 1; i < n - 1; i++) {
| |
− | P[i].u += P[i].v * dt;
| |
− | }
| |
− | }
| |
− | t += dt;
| |
− | step++;
| |
− | | |
− | // промежуточная прорисовка результатов, работа прогресс-бара
| |
− | if ((performance.now() - t1) > 200) {
| |
− | if (working) {
| |
− | draw();
| |
− | setTimeout( function(){calculate(all_P); }, 10);
| |
− | div_container_progress.style.display = "block";
| |
− | progress_bar.style.width = Math.round(t / T * 100) + "%";
| |
− | span_progress.innerHTML = (t / T * 100).toFixed(0) + "%";
| |
− | } else {
| |
− | stop();
| |
− | }
| |
− | return;
| |
− | }
| |
− | }
| |
− | stop();
| |
− | }
| |
− | function stop() {
| |
− | // окончательная прорисовка результатов, удаление прогресс-бара, вывод скорости расчета
| |
− | draw();
| |
− | div_container_progress.style.display = "none";
| |
− | button_start.style.display = "inline";
| |
− | button_stop.style.display = "none";
| |
− | div_calc_speed.style.display = "block";
| |
− | span_time_calc.innerHTML = parseFloat(((performance.now() - t_start) * 1000 * 1000 / N / R / step).toPrecision(2));
| |
− | return true;
| |
− | }
| |
− | | |
− | function draw() {
| |
− | ctx.clearRect(0, 0, w, h); // очистка экрана
| |
− | | |
− | if (checkbox_Bessel.checked) {
| |
− | // Функция Бесселя первого рода в точке 0
| |
− | ctx.strokeStyle = "#00dd00";
| |
− | ctx.lineWidth = 2;
| |
− | ctx.beginPath();
| |
− | ctx.moveTo(0, h - data_E[data_E.length - 1] * besselj(4 * Math.sqrt(C / m) * 0, 0) / data_K[0] * h / 2 - h / 2);
| |
− | for (var i = 0.001; i < t; i += 0.001) {
| |
− | ctx.lineTo(i / t * w, h - data_E[data_E.length - 1] * besselj(4 * Math.sqrt(C / m) * i, 0) / data_K[0] * h / 2 - h / 2);
| |
− | }
| |
− | ctx.stroke();
| |
− | }
| |
− | | |
− | if (checkbox_K.checked) {
| |
− | // Кинетическая энергия
| |
− | ctx.strokeStyle = "#ff0000";
| |
− | ctx.lineWidth = 1;
| |
− | ctx.beginPath();
| |
− | ctx.moveTo(0, 0);
| |
− | for (var i = 1; i < data_K.length; i++) {
| |
− | ctx.lineTo(i / (data_K.length - 1) * w, h - data_K[i] / data_K[0] * h);
| |
− | }
| |
− | ctx.stroke();
| |
− | }
| |
− | | |
− | if (checkbox_P.checked) {
| |
− | // Потенциальная энергия
| |
− | ctx.strokeStyle = "#0000ff";
| |
− | ctx.lineWidth = 1;
| |
− | ctx.beginPath();
| |
− | ctx.moveTo(0, h - data_P[0] / data_K[0] * h);
| |
− | for (var i = 1; i < data_P.length; i++) {
| |
− | ctx.lineTo(i / (data_P.length - 1) * w, h - data_P[i] / data_K[0] * h);
| |
− | }
| |
− | ctx.stroke();
| |
− | }
| |
− | | |
− | if (checkbox_E.checked) {
| |
− | // Полная энергия
| |
− | ctx.strokeStyle = "#880088";
| |
− | ctx.lineWidth = 2;
| |
− | ctx.beginPath();
| |
− | ctx.moveTo(0, h - data_E[0] / 2 / data_K[0] * h);
| |
− | for (var i = 1; i < data_E.length; i++) {
| |
− | ctx.lineTo(i / (data_E.length - 1) * w, h - data_E[i] / 2 / data_K[0] * h);
| |
− | }
| |
− | ctx.stroke();
| |
− | }
| |
− | }
| |
− | }
| |
− | </syntaxhighlight>
| |
− | | |
− | Файл '''"Lang.js"'''
| |
− | <syntaxhighlight lang="javascript" line start="1" enclose="div">
| |
− | strings = {
| |
− | span_kin_energy:{
| |
− | field:"innerHTML",
| |
− | en:"Kinetic energy",
| |
− | ru:"Кинетическая энергия"
| |
− | }, span_pot_energy:{
| |
− | field:"innerHTML",
| |
− | en:"Potential energy",
| |
− | ru:"Потенциальная энергия"
| |
− | }, span_full_energy:{
| |
− | field:"innerHTML",
| |
− | en:"Full energy",
| |
− | ru:"Полная энергия"
| |
− | }, span_txt_Bessel:{
| |
− | field:"innerHTML",
| |
− | en:"Analytical sol. for the kinetic energy",
| |
− | ru:"Аналит. решение для кин. энергии"
| |
− | }, button_start:{
| |
− | field:"value",
| |
− | en:"Start",
| |
− | ru:"Старт"
| |
− | }, button_stop:{
| |
− | field:"value",
| |
− | en:"Stop",
| |
− | ru:"Стоп"
| |
− | }, span_progress_txt:{
| |
− | field:"innerHTML",
| |
− | en:"Progress: ",
| |
− | ru:"Прогресс: "
| |
− | }, abbr_speed:{
| |
− | field:"title",
| |
− | en:"The calculation of this speed includes the time for processing interface and drawing the intermediate states of the system",
| |
− | ru:"Расчет данной скорости включает в себя время на обработку интерфейса и прорисовку промежуточных состояний системы"
| |
− | }, span_txt_molecular_dynamics:{
| |
− | field:"innerHTML",
| |
− | en:"Molecular_dynamics:",
| |
− | ru:"Молекулярная динамика:"
| |
− | }, span_txt_particles:{
| |
− | field:"innerHTML",
| |
− | en:"particles",
| |
− | ru:"частиц"
| |
− | }, span_txt_realizations:{
| |
− | field:"innerHTML",
| |
− | en:"realizations",
| |
− | ru:"реализаций"
| |
− | }, span_txt_calc_time:{
| |
− | field:"innerHTML",
| |
− | en:"Calculation time:",
| |
− | ru:"Время расчета:"
| |
− | }, span_txt_calc_speed:{
| |
− | field:"innerHTML",
| |
− | en:"Calculation speed:",
| |
− | ru:"Скорость расчета:"
| |
− | }, span_txt_ns_particle_step:{
| |
− | field:"innerHTML",
| |
− | en:"ns/(particle⋅step)",
| |
− | ru:"нс/(частица⋅шаг)"
| |
− | }, span_txt_periods:{
| |
− | field:"innerHTML",
| |
− | en:"periods",
| |
− | ru:"периодов"
| |
− | }, div_txt_P:{
| |
− | field:"innerHTML",
| |
− | en:"P",
| |
− | ru:"П"
| |
− | }
| |
− | };
| |
− | | |
− | function set_lang(lang){
| |
− | for (var s in strings) {
| |
− | document.getElementById(s)[strings[s].field] = strings[s][lang];
| |
− | }
| |
− | }
| |
− | </syntaxhighlight>
| |
− | | |
− | Файл '''"Bessel_fluctuations.html"'''
| |
− | <syntaxhighlight lang="html5" enclose="div">
| |
− | <!DOCTYPE html>
| |
− | <html>
| |
− | <head>
| |
− | <meta charset="UTF-8" />
| |
− | <title>Bessel fluctuations</title>
| |
− | <script src="Bessel_fluctuations.js"></script>
| |
− | <script src="Lang/Lang.js"></script>
| |
− | <script src="Libs/bessel.js"></script>
| |
− | <style>
| |
− | table.outer td, table.outer tr {border: 1px solid #ddd; padding-right: 10px; padding-left: 5px}
| |
− | table.inner td, table.inner tr {border: 0}
| |
− | </style>
| |
− | </head>
| |
− | <body>
| |
− | <table style="border-collapse:collapse;">
| |
− | <tr><td style="text-align: center; vertical-align: top; width: 25px;">
| |
− | <div id="div_txt_J0" style="color: #00dd00; font-style:italic;">K<sub>J</sub></div>
| |
− | <div id="div_txt_K" style="color: #ff0000; font-style:italic;">K</div>
| |
− | <div id="div_txt_P" style="color: #0000ff; font-style:italic;"></div>
| |
− | <div id="div_txt_E" style="color: #880088; font-style:italic;">E/2</div>
| |
− | </td><td>
| |
− | <canvas id="BF_canvas" width="1000" height="500" style="border:1px solid #000000; display: block "></canvas>
| |
− | </td></tr><tr><td></td><td style="text-align: right;">
| |
− | <div style="color: #444444; font-style:italic; margin-top:-5px">x</div>
| |
− | </td></tr><tr><td colspan="2">
| |
− | | |
− | <table class="outer" style="border-collapse: collapse; width:100%">
| |
− | <tr>
| |
− | <td style="width: 270px">
| |
− | <input type="checkbox" id="checkbox_Bessel" checked/><font color="#00dd00" size="5"><B>—</B></font> <span id="span_txt_Bessel"></span> <br>
| |
− | <input type="checkbox" id="checkbox_K" checked/><font color="#ff0000" size="5"><B>—</B></font> <span id="span_kin_energy"></span> <br>
| |
− | <input type="checkbox" id="checkbox_P"/><font color="#0000ff" size="5"><B>—</B></font> <span id="span_pot_energy"></span> <br>
| |
− | <input type="checkbox" id="checkbox_E"/><font color="#880088" size="5"><B>—</B></font> <span id="span_full_energy"></span> <br>
| |
− | </td><td>
| |
− | <input type="button" id="button_start" style="background:#fb4;border-radius: 5px;color:#000; font-weight: bold;"/>
| |
− | <input type="button" id="button_stop" style="background:#fb4;border-radius: 5px;color:#000; font-weight: bold; display:none"/><br>
| |
− | <input type="image" src="Lang/RU.png" onclick="set_lang('ru')"/>
| |
− | <input type="image" src="Lang/GB.png" onclick="set_lang('en')"/><br>
| |
− | <div id="div_container_progress" style="display: none;">
| |
− | <span id="span_progress_txt"></span><span id="span_progress"></span>
| |
− | <div id="container_bar" style="width:200px; height:20px; border:1px solid black;">
| |
− | <div id="progress_bar" style="width:10%;background-color: orange; height:20px;"></div>
| |
− | </div>
| |
− | </div>
| |
− | | |
− | <div id="div_calc_speed" style="display: none">
| |
− | <abbr id="abbr_speed" style="border-bottom: 1px dotted black;">
| |
− | <span id="span_txt_calc_speed"></span> <span id="span_time_calc"></span> <span id="span_txt_ns_particle_step"></span>
| |
− | </abbr>
| |
− | </div>
| |
− | | |
− | </td><td style="width: 320px">
| |
− | <table class="inner">
| |
− | <tr>
| |
− | <td>
| |
− | <span id="span_txt_molecular_dynamics"></span>
| |
− | </td>
| |
− | </tr><tr>
| |
− | <td>
| |
− | <input type="number" id="N_number" step="1" min="2" style="width: 70px;"/> <span id="span_txt_particles"></span>,
| |
− | <input type="number" id="R_number" step="1" min="1" style="width: 70px;"/> <span id="span_txt_realizations"></span><br><br>
| |
− | </td>
| |
− | </tr><tr>
| |
− | <td>
| |
− | <span id="span_txt_calc_time"></span>
| |
− | </td>
| |
− | </tr><tr>
| |
− | <td>
| |
− | <input type="number" id="periods_number" step="0.1" min="0" style="width: 70px;"/> <span id="span_txt_periods"></span>
| |
− | </td>
| |
− | </tr>
| |
− | | |
− | </table>
| |
− | </td>
| |
− | </tr>
| |
− | </table>
| |
− | | |
− | </td></tr></table>
| |
− | | |
− | <script>set_lang("ru")</script>
| |
− | </body>
| |
− | </html>
| |
− | </syntaxhighlight>
| |
− | </div>
| |
− | </div>
| |
− | | |
− | == Старые версии программы ==
| |
− | * [[Колебания энергий в одномерном кристалле v2.5]]
| |
− | | |
− | [[Category: Виртуальная лаборатория]]
| |
− | [[Category: Программирование]]
| |
− | [[Category: Проект "Термокристалл"]]
| |