Редактирование: Сравнение методов Рунге-Кутта и Липфрога

Перейти к: навигация, поиск

Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.

Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия Ваш текст
Строка 1: Строка 1:
 
[[Виртуальная лаборатория]]>[[Сравнение методов Рунге-Кутта и Липфрога]] <HR>
 
[[Виртуальная лаборатория]]>[[Сравнение методов Рунге-Кутта и Липфрога]] <HR>
 +
Сравнение методов численного интегрирования: Рунге-Кутта и Липфрога
  
Перед прочтением статьи рекомендуется просмотреть раздел "Обсуждение"
+
В данном примере интегрируется уравнение грузика на пружинке: <math>\ddot{x} = -cx</math> методом Рунге-Кутта и Липфрога. Строится фазовая плоскость для каждого из методов.
  
== '''Постановка задачи ''' ==
+
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Pogodina/Integrate/Integrate.html |width=1000 |height=2000 |border=0 }}
Дано простейшее уравнение движения грузика на пружине: <math>\ddot{x} = -cx</math>. Необходимо интегрировать его с помощью двух методов: leapfrog и Рунге-Кутта. Построить фазовую плоскость для каждого из методов и сравнить результаты.
 
<br/>
 
  
== '''Метод численного интегрирования Рунге-Кутты''' ==
+
Скачать [[Медиа:Integrate1.rar|Integrate1.rar]].
Для нашего уравнения алгоритм будет выглядеть следующим образом:<br />
 
Вычисление нового значения проходит в четыре стадии:<br />
 
<math>kv_1 = dt(-x(t))</math><br />
 
<math>kv_2 = dt(-x(t)+\frac{kv_1}{2})</math><br />
 
<math>kv_3 = dt(-x(t)+\frac{kv_2}{2})</math><br />
 
<math>kv_4 = dt(-x(t)+kv_3)</math><br />
 
<br />
 
<math>kr_1 = dt\dot{x}(t)</math><br />
 
<math>kr_2 = dt(\dot{x}(t)+\frac{kr_1}{2})</math><br />
 
<math>kr_3 = dt(\dot{x}(t)+\frac{kr_2}{2})</math><br />
 
<math>kr_4 = dt(\dot{x}(t)+kv_3)</math><br />
 
где <math>dt</math> - шаг интегрирования.<br />
 
Тогда приближенное значение в последующих точках вычисляется по итерационной формуле:<br />
 
<math>\dot{x}(t+dt) = \dot{x}(t) + \frac{h}{6}(kr_1 + 2kr_2 + 2kr_3 + kr_4)</math><br />
 
<math>x(t+dt) = x(t) + \frac{h}{6}(kv_1 + 2kv_2 + 2kv_3 + kv_4)</math><br />
 
  
=='''Метод численного интегрирования leapfrog'''==
 
Для уравнения второй степени скорость и перемещение находятся следующим образом:<br />
 
<math>\dot{x}(t+dt) = \dot{x}(t)-x(t)dt</math><br />
 
<math>x(t+dt) = x(t)+\dot{x}(t+dt)dt</math><br />
 
 
                            '''Метод Рунге-Кутта'''                                                            '''Метод leapfrog'''
 
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Pogodina/Integrate/particles2.html |width=1300|height=800 |border=0 }}
 
<br />
 
<br />
 
Скачать программу [[Медиа:Particles1.rar|Particles1.rar]].
 
<br />
 
<br />
 
 
<div class="mw-collapsible mw-collapsed" style="width:100%" >
 
<div class="mw-collapsible mw-collapsed" style="width:100%" >
'''Текст программы на языке JavaScript (разработчик [[Погодина Валерия]]):''' <div class="mw-collapsible-content">
+
'''Текст программы на языке JavaScript (разработчик [[Погодина Валерия]], код основан на программе [[Цветков Денис]]):''' <div class="mw-collapsible-content">
Файл '''"Particles1.js"'''
+
Файл '''"Integral3"'''
 
<syntaxhighlight lang="javascript" line start="1" enclose="div">
 
<syntaxhighlight lang="javascript" line start="1" enclose="div">
<!DOCTYPE html>
+
window.addEventListener("load", Main_Integrate, true);
<html>
+
function Main_Integrate() {
<head>
+
    <meta charset="UTF-8" />
 
    <title> Particle</title>
 
    <script src="Particles2.js"></script>
 
<!--    <script src="jquery.min.js"></script>
 
    <script src="jquery.flot.js"></script> -->
 
</head>
 
<body>
 
<br>
 
<table><tr valign="top">
 
<td>
 
    <canvas id="canvasGraph" width="600" height="600" style="border:1px solid #000000;"></canvas>
 
<canvas id="canvasGraph1" width="600" height="600" style="border:1px solid #000000;"></canvas>
 
</td>
 
<!-- <td>
 
<input type="button" id="drop_spring" value="Drop Spring"/><br>
 
<br/>
 
<input type="button" id="new_static" value="New Static"/><br>
 
<br>
 
    <input type="range" id="slider_m" min="0.1" max="1.5" step=0.1 style="width: 150px;" />
 
    Масса грузиков = <input type="number" id="number_m" min="0.1" max="1.5" step=0.1 style="width: 50px;" /><br>
 
 
<input type="range" id="slider_spf" min="1" max="15" step=1 style="width: 150px;" />
 
    Скорость протекания процесса = <input type="number" id="number_spf" min="1" max="15" step=1 style="width: 50px;" /><br> -->
 
 
<input type="range" id="slider_n" min="1" max="100" step=1 style="width: 150px;" />
 
    Количество частиц = <input type="number" id="number_n" min="1" max="100" step=1 style="width: 50px;" /><br>
 
<br>
 
<input type="range" id="slider_dt" min="0.0001" max="0.01" step=0.0001 style="width: 150px;" />
 
    dt = <input type="number" id="number_dt" min="0.0001" max="0.01" step=0.0001 style="width: 50px;" /><br>
 
<br>
 
<script
 
type="text/javascript"> app = new MainParticle(document.getElementById('canvasGraph'),document.getElementById('canvasGraph1'));
 
</script>
 
<!-- График перемещений последнего грузика:
 
    <div id="vGraph1" style="width:400px; height:200px; clear:both;"></div> -->
 
 
 
 
</tr></table>
 
</body>
 
</html>
 
function MainParticle(canvas_gr, canvas_gr1) {
 
 
     // Предварительные установки
 
     // Предварительные установки
var context_gr  = canvas_gr.getContext("2d");  // на context происходит рисование
+
var context_gr1  = canvas_gr1.getContext("2d");  // на context происходит рисование
+
    var context = Integrate_canvas.getContext("2d");  // на context происходит рисование
  //  Задание констант
+
var context1 = Integrate_canvas1.getContext("2d");  // на context происходит рисование
    const Pi = 3.1415926;                  // число "пи"
+
var T0 = 1;                          // масштаб времени (период колебаний исходной системы)
    const T0 = 1;                          // масштаб времени (период колебаний исходной системы)
+
var time = 0;
    const a0 = 1;                          // масштаб расстояния (диаметр шара)
 
 
 
    const k0 = 2 * Pi / T0;                // масштаб частоты
 
 
 
    // *** Задание физических параметров ***
 
 
 
    const Ny = 5;                          // число шаров, помещающихся по вертикали в окно (задает размер шара относительно размера окна)
 
 
 
var vx0 = 1 * a0 / T0;
 
 
 
 
 
 
 +
// *** Задание вычислительных параметров ***
 +
 +
    //const fps = 5500;                        // frames per second - число кадров в секунду (качеcтво отображения)
 +
    //const spf = 260;                        // steps per frame  - число шагов интегрирования между кадрами (скорость расчета)
 +
    //const dt  = 0.1 * T0 / fps;          // шаг интегрирования
 
 
 +
const fps = 550;                        // frames per second - число кадров в секунду (качеcтво отображения)
 +
    const spf = 5;                        // steps per frame  - число шагов интегрирования между кадрами (скорость расчета)
 +
    const dt  = 1 * T0;          // шаг интегрирования
 +
var n = 10;
 
 
    // *** Задание вычислительных параметров ***
+
Text_n.value = n;
 
+
Slider_n.min = 1;                        
    const fps = 50;                        // frames per second - число кадров в секунду (качеcтво отображения)
+
    Slider_n.max = 100;
    const spf = 100;                        // steps per frame  - число шагов интегрирования между кадрами (скорость расчета)
+
    Slider_n.step = 1;
    var dt = 0.2 * T0 / fps;  
+
    Slider_n.value = Text_n.value;
var n = 40; // шаг интегрирования
 
slider_n.value = parseInt(n);
 
number_n.value = parseInt(n);
 
slider_dt.value = dt;
 
number_dt.value = dt;
 
 
 
        function setN(new_n) {
+
    // Добавление шара
                n = new_n;
+
var particles = [];
for (var z = 0; z < n; z++) {
+
var particles1 = [];
b[z] = [];
+
for (var i=0; i<n; i++) {
a[z] = [];
+
particles[i] = [];
 +
particles1[i] = [];
 
}
 
}
for (var i = 0; i< n; i++) {
+
        for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
+
for (var j = 0; j < n; j++) {
c = [];
+
var b = [];
d = [];
+
var a = [];
c.x = w / 3 / n * i;
+
b.x = 0.3 / n * i;
c.vx = 2 * vx0 / n * j;
+
b.vx =j * 0.3 / n;
d.x = w / 3 / n * i;
+
a.x = 0.3 / n * i;
d.vx = 2 * vx0 / n * j;
+
a.vx =j * 0.3 / n;
b[i][j] = c;
+
particles[i][j] = b;
a[i][j] = d;
+
particles1[i][j] = a;
}
+
}
}
 
context_gr.clearRect(0, 0, w * scale, h * scale);
 
context_gr1.clearRect(0, 0, w * scale, h * scale);
 
 
         }
 
         }
 
 
function setdt(new_dt) {
+
        this.set_n = function(input)
dt = new_dt;
+
        {
for (var i = 0; i< n; i++) {
+
                n = Number(input);
for (var j = 0; j < n; j++) {
+
                Text_n.value  = n;
c = [];
+
                Slider_n.value = Text_n.value; //записываем значение начального смещения
d = [];
+
for (var i=0; i<n; i++) {
c.x = w / 3 / n * i;
+
particles[i] = [];
c.vx = 2 * vx0 / n * j;
+
particles1[i] = [];
d.x = w / 3 / n * i;
+
}
d.vx = 2 * vx0 / n * j;
+
for (var i = 0; i < n; i++) {
b[i][j] = c;
+
for (var j = 0; j < n; j++) {
a[i][j] = d;
+
var b = [];
}
+
var a = [];
}
+
b.x = 0.3 / n * i;
context_gr.clearRect(0, 0, w * scale, h * scale);
+
b.vx = j * 0.3 / n;
context_gr1.clearRect(0, 0, w * scale, h * scale);
+
a.x = 0.3 / n * i;
 +
a.vx = j * 0.3 / n;
 +
particles[i][j] = b;
 +
particles1[i][j] = a;
 +
}
 +
}
 +
                context.clearRect(0, 0, 300, 300);    
 +
                context1.clearRect(0, 0, 300, 300);  
 
         }
 
         }
+
slider_n.oninput = function () {
 
number_n.value = slider_n.value;
 
setN(slider_n.value);
 
        };
 
 
number_n.oninput = function () {
 
slider_n.value = number_n.value;
 
setN(number_n.value);
 
        };
 
 
 
slider_dt.oninput = function () {
 
number_dt.value = slider_dt.value;
 
setdt(slider_dt.value);
 
        };
 
 
number_dt.oninput = function () {
 
slider_dt.value = number_dt.value;
 
setdt(number_dt.value);
 
        };
 
  
 +
setInterval(control1, 1500 / fps);
 
 
+
function control1() {
// Задание констант для рисования
+
physics1();
const scale = canvas_gr.height / Ny / a0;  // масштабный коэффициент для перехода от расчетных к экранным координатам
+
draw();
+
}
var w = canvas_gr.width / scale;           // ширина окна в расчетных координатах
 
    var h = canvas_gr.height / scale;         // высота окна в расчетных координатах
 
 
  
    // -------------------------------        Выполнение программы              ------------------------------------------
+
function physics1() {                    // то, что происходит каждый шаг времени
// Добавление шара
+
        for (var s = 1; s <= spf; s++) {
var b = [];
+
for (i = 0; i < n; i++) {
var a = [];
+
for (j = 0; j < n; j++) {
for (var z = 0; z < n; z++) {
+
runge();
b[z] = [];
+
leapfrog();
a[z] = [];
+
}
}
+
}
for (var i = 0; i< n; i++) {
+
        }
for (var j = 0; j < n; j++) {
+
    }
c = [];
 
d = [];
 
c.x = w / 3 / n * i;
 
c.vx = 2 * vx0 / n * j;
 
d.x = w / 3 / n * i;
 
d.vx = 2 * vx0 / n * j;
 
b[i][j] = c;
 
a[i][j] = d;
 
}
 
}
 
 
 
// Основной цикл программы
+
function leapfrog(){
setInterval(control, 1500 / fps); // функция control вызывается с периодом, определяемым вторым параметром
+
particles1[i][j].vx = particles1[i][j].vx - particles1[i][j].x * dt;        
+
particles1[i][j].x = particles1[i][j].x + particles1[i][j].vx * dt;
// ---------------------------------------------------------------------------------------------------------------------
+
console.log(particles1[0][0].x);
// ---------------------------------          Определение всех функций              -----------------------------------
+
        }
// ---------------------------------------------------------------------------------------------------------------------
 
 
 
// основная функция, вызываемая в программе
+
function runge() {
function control()  
+
var k1, k2, k3, k4;
{
+
k1 = - (particles[i][j].x);
        physics(); // делаем spf шагов интегрирование
+
k2 = - (particles[i][j].x + k1 * dt / 2);
draw_gr(); // рисуем график
+
k3 = - (particles[i][j].x + k2 * dt / 2);
    }
+
k4 = - (particles[i][j].x + k3 * dt);
 +
particles[i][j].vx = particles[i][j].vx + dt / 6 * (k1 + 2 * k2 + 2 * k3 + k4);
 +
k1 = (particles[i][j].vx);
 +
k2 = (particles[i][j].vx + k1 * dt / 2);
 +
k3 = (particles[i][j].vx + k2 * dt / 2);
 +
k4 = (particles[i][j].vx + k3 * dt);
 +
particles[i][j].x = particles[i][j].x + dt / 6 * (k1 + 2 * k2 + 2 * k3 + k4);
 +
console.log(particles[0][0].x);
 +
}
  
+
function draw() {
    // Функция, делающая spf шагов интегрирования
+
context.clearRect(0, 0, 600, 600);
    function physics() {                   // то, что происходит каждый шаг времен
+
context.fillStyle="#000000";
for (var s = 1; s <= spf; s++) {
+
context.beginPath();
for (var k = 0; k < n; k++) {
+
context.moveTo(0, 300);
for (var p = 0; p < n; p++) {
+
context.lineTo(600, 300);
+
context.stroke();
k1v = dt*(-( b[k][p].x));
+
context.beginPath();
k2v = dt*(-( b[k][p].x)  + k1v/2);
+
context.moveTo(300, 0);
k3v = dt*(-( b[k][p].x)  + k2v/2);
+
context.lineTo(300, 600);
k4v = dt*(-( b[k][p].x) + k3v);
+
context.stroke();
 
+
context1.clearRect(0, 0, 600, 600);
k1r = dt* b[k][p].vx;
+
context1.fillStyle="#000000";
k2r = dt*(b[k][p].vx + k1r/2);
+
context1.beginPath();
k3r = dt*(b[k][p].vx + k2r/2);
+
context1.moveTo(0, 300);
k4r = dt*(b[k][p].vx + k3r);
+
context1.lineTo(600, 300);
 
+
context1.stroke();
b[k][p].vx += (k1v + 2*k2v + 2*k3v + k4v)/6;
+
context1.beginPath();
b[k][p].x  += (k1r + 2*k2r + 2*k3r + k4r)/6;
+
context1.moveTo(300, 0);
+
context1.lineTo(300, 600);
 +
context1.stroke();
 +
for (var i = 0; i < n; i++) {
 +
for (var j = 0; j < n; j++) {
 +
context.beginPath();
 +
context.arc(particles[i][j].x * 300 + 300, 300 - particles[i][j].vx * 300, 1, 0, 2 * Math.PI, false);                  //рисуем шар
 +
context.fill();
 +
context.closePath();
 
 
a[k][p].vx = a[k][p].vx - a[k][p].x * dt;        
+
context1.beginPath();
a[k][p].x = a[k][p].x + a[k][p].vx * dt;  
+
context1.arc(particles1[i][j].x * 300 + 300, 300 - particles1[i][j].vx * 300, 1, 0, 2 * Math.PI, false);                  //рисуем шар
        }
+
context1.fill();
 +
context1.closePath();
 
}
 
}
}
 
}
 
 
 
 
 
 
// Определение функции, рисующей график
 
context_gr.fillStyle = "#3070d0"; // цвет
 
context_gr.strokeStyle = "#ff0000";
 
context_gr1.fillStyle = "#3070d0"; // цвет
 
context_gr1.strokeStyle = "#ff0000";
 
function draw_gr()
 
{
 
context_gr.clearRect(0, 0, w * scale, h * scale);
 
context_gr.beginPath();
 
context_gr.strokeStyle = "#000000";
 
 
context_gr1.clearRect(0, 0, w * scale, h * scale);
 
context_gr1.beginPath();
 
context_gr1.strokeStyle = "#000000";
 
 
// ось
 
context_gr.moveTo(w/2*scale, (h)*scale);
 
context_gr.lineTo(w/2*scale, -h*scale);
 
context_gr1.moveTo(w/2*scale, (h)*scale);
 
context_gr1.lineTo(w/2*scale, -h*scale);
 
 
// ось
 
context_gr.moveTo(0, (h/2)*scale);
 
context_gr.lineTo((w)*scale, (h/2)*scale);
 
context_gr1.moveTo(0, (h/2)*scale);
 
context_gr1.lineTo((w)*scale, (h/2)*scale);
 
 
        context_gr.closePath();
 
context_gr.stroke();
 
        context_gr1.closePath();
 
context_gr1.stroke();
 
 
// график
 
for (var l = 0; l< n; l++) {
 
for (var m = 0; m < n; m++) {
 
context_gr.beginPath();
 
context_gr.arc((b[l][m].x + w/2)* scale, (-b[l][m].vx + h / 2) * scale, 1, 0, 2 * Math.PI, false);                  //рисуем шар
 
context_gr.fill();
 
context_gr.closePath();
 
 
context_gr1.beginPath();
 
context_gr1.arc((a[l][m].x + w/2)* scale, (-a[l][m].vx + h / 2) * scale, 1, 0, 2 * Math.PI, false);                  //рисуем шар
 
context_gr1.fill();
 
context_gr1.closePath();
 
 
 
}
 
}
}
+
}  
+
}
}
+
</syntaxhighlight>
}
+
Файл '''"Chain_v3_release.html"'''
 +
<syntaxhighlight lang="html5" line start="1" enclose="div">
 +
<!DOCTYPE html>
 +
    <html>
 +
    <head>
 +
        <meta charset="UTF-8"/>
 +
        <title> Integrate </title>
 +
        <script src="Integral3.js"></script>
 +
    </head>
 +
    <body>
 +
        <canvas id="Integrate_canvas" width="600" height="600" style="border:1px solid #000000;"></canvas>
 +
<canvas id="Integrate_canvas1" width="600" height="600" style="border:1px solid #000000;"></canvas>
 +
            <div>
 +
                            <!-- n-->
 +
            <div>
 +
                n =
 +
            <input id="Text_n" style="width: 4.2ex;" required pattern="[-+]?([0-9]*\.[0-9]+|[0-9]+)" oninput="
 +
              if (!this.checkValidity()) return;
 +
              app.set_n(this.value);
 +
              document.getElementById('Slider_n').value = this.value;
 +
          ">
 +
                    <input type = "range"  id="Slider_n" style="width: 100px;" oninput="app.set_n(this.value); document.getElementById('Text_n').value = this.value;">
 +
            </I></font>
 +
        </div>
 +
        </div>   
 +
            <script type="text/javascript"> app = new Main_Integrate(document.getElementById('Integrate_canvas'),document.getElementById('Integrate_canvas1'));</script>   
 +
    </body>
 +
    </html>
 
</syntaxhighlight>
 
</syntaxhighlight>
 
</div>
 
</div>
 
</div>
 
</div>
  
=='''Выводы'''==
 
Мы наблюдаем симплектический характер метода Липфрога: сохраняет энергию(слегка измененную). Метод Рунге-Кутты напротив не соханяет энергию системы.
 
 
=='''Ссылки'''==
 
*[https://en.wikipedia.org/wiki/Leapfrog_integration leapfrog]
 
*[https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%A0%D1%83%D0%BD%D0%B3%D0%B5_%E2%80%94_%D0%9A%D1%83%D1%82%D1%82%D1%8B Рунге-Кутты]
 
*[[Курсовые работы по ВМДС: 2015-2016]]
 
*[[Введение в механику дискретных сред]]
 
* [[Виртуальная лаборатория]]
 
<br/>
 
 
[[Category: Виртуальная лаборатория]]
 
[[Category: Виртуальная лаборатория]]
 
[[Category: Программирование]]
 
[[Category: Программирование]]
 
[[Category: JavaScript]]
 
[[Category: JavaScript]]
Вам запрещено изменять защиту статьи. Edit Создать редактором

Обратите внимание, что все добавления и изменения текста статьи рассматриваются как выпущенные на условиях лицензии Public Domain (см. Department of Theoretical and Applied Mechanics:Авторские права). Если вы не хотите, чтобы ваши тексты свободно распространялись и редактировались любым желающим, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого.
НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ МАТЕРИАЛЫ, ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ!

To protect the wiki against automated edit spam, we kindly ask you to solve the following CAPTCHA:

Отменить | Справка по редактированию  (в новом окне)