2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение20.11.2019, 08:52 
Аватара пользователя


11/12/16
13852
уездный город Н
Lorein_
Пожалуйста. Надеюсь заработало.

А если заработало, то можно подумать и об оптимизации.
Вы в теле цикла вызываете три раза $rk4(x, u, h)$ с одними и теми же параметрами.
А это основное время.

Код:
            for (int i = 0; i < n; i++)
            {
                V = rk4(x, u, h); // Раз
                chart1.Series[0].Points.AddXY(x, rk4(x, u, h)); // Два
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = i;
                dataGridView1.Rows[i].Cells[1].Value = x;
                dataGridView1.Rows[i].Cells[2].Value = h;
                dataGridView1.Rows[i].Cells[3].Value = f(x, u);
                dataGridView1.Rows[i].Cells[4].Value = V;
                dataGridView1.Rows[i].Cells[5].Value = Vi;
                dataGridView1.Rows[i].Cells[6].Value = V_2i;
                dataGridView1.Rows[i].Cells[7].Value = S;
               x += h;
                u = rk4(x, u, h); // Три
               
            }


Достаточно одной таблэтки (с)

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение20.11.2019, 17:56 
Экс-модератор
Аватара пользователя


23/12/05
12064
EUgeneUS, аргументы, скармливаемые rk4() между вторым и третьим вызовом меняются.

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение20.11.2019, 19:39 
Аватара пользователя


11/12/16
13852
уездный город Н
photon
А это очередной косяк. Рунге-Кутту надо скармливать текущий $x_ n$, чтобы получить $y_{ n+1}$, а потом уже двигать $x$ в $x_{n+1}$

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение23.11.2019, 19:25 


10/12/17
50
Цитата:
А это очередной косяк. Рунге-Кутту надо скармливать текущий $x_ n$, чтобы получить $y_{ n+1}$, а потом уже двигать $x$ в $x_{n+1}$

Да,сразу не заметила его. Значение функции теперь действительно является квадратом x.
Только ведь цикл начинается с 0.И получается такая ситуация,что в datagridview $x_0=0 $соответствует численное решение равное 0.04.
А $y(x_0)=0 $ это задача Коши и в DGV $x_0=0$ должно соответствовать значение 0.
А если цикл начинать с 1,то столбец полностью пустой на выходе.

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение23.11.2019, 21:48 
Аватара пользователя


11/12/16
13852
уездный город Н
Lorein_ в сообщении #1427357 писал(а):
Только ведь цикл начинается с 0.И получается такая ситуация,что в datagridview $x_0=0 $соответствует численное решение равное 0.04.
А $y(x_0)=0 $ это задача Коши и в DGV $x_0=0$ должно соответствовать значение 0.


Проблема не в том, с чего начинается цикл, а в том, что в datagridview с индексом $i$ Вы пишите $x_i$ и $y_{i+1}$.

Я бы в datagridview.Raws[0] писал начальные значения вне цикла. А в цикле бы писал значения для $ i+1$.

Lorein_ в сообщении #1427357 писал(а):
А если цикл начинать с 1,то столбец полностью пустой на выходе.

С этим не разбирался.

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение23.11.2019, 21:59 


10/12/17
50
Цитата:
Я бы в datagridview.Raws[0] писал начальные значения вне цикла. А в цикле бы писал значения для $ i+1$.

Получается пустая таблица с заполненной последней строкой но и она так же заполнена неверно.Для $x=2$ получаем $V=4,84$

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение25.11.2019, 19:37 


10/12/17
50
Точнее говоря, пустой столбец V.
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RungeKutta
{
    public partial class Form1 : Form
    {
       


        public Form1()
        {
            InitializeComponent();
        }

        double f(double x, double u)
        {
         
            return 2 * x - u + x * x;
        }
        double rk4(double x, double u, double h)
        {
         
            double k1, k2, k3, k4, u1;
            k1 = h * f(x, u);
            k2 = h * f(x + 0.5* h, u + 0.5 * k1);
            k3 = h * f(x + 0.5* h, u + 0.5 * k2);
            k4 = h * f(x + h, u + k3);
            u1 = u + (1.0 / 6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
            return u1;
        }

     

        private void button1_Click(object sender, EventArgs e)
        {
            chart1.Series[0].Points.Clear();
            dataGridView1.Visible = true;
            dataGridView1.Rows.Clear();
            dataGridView1.Columns.Clear();
            dataGridView1.ColumnCount = 10;
           
            dataGridView1.Columns[0].HeaderText = "i";
            dataGridView1.Columns[1].HeaderText = "x";
            dataGridView1.Columns[2].HeaderText = "h";
            dataGridView1.Columns[3].HeaderText = "f(x,u)";
            dataGridView1.Columns[4].HeaderText = "V";
       

            double x = 0;
            double u = 0;
            double h = 0.2;
            double b = 2.2;

            double n = (b - x) / h;
         
            double Vi = 0,  S = 0, V = 0;

           
            dataGridView1.Rows[0].Cells[4].Value = 0;

            for (int i = 0; i<n; i++)
            {

                V = rk4(x, u, h);
                chart1.Series[0].Points.AddXY(x,V);
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = i;
                dataGridView1.Rows[i].Cells[1].Value = x;
                dataGridView1.Rows[i].Cells[2].Value = h;
                dataGridView1.Rows[i].Cells[3].Value = f(x, u);
                dataGridView1.Rows[i+1].Cells[4].Value = V ;

                u = rk4(x, u, h);
                x += h;

            }
           
        }


    }
}

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение26.11.2019, 08:35 
Аватара пользователя


11/12/16
13852
уездный город Н
1. Довольно странное решение писать внутри цикла все переменные $i$-е, а только одну ($V$) $i+1$-ю.
2. Как нетрудно видеть в последней строке ($i+1$-й) должно быть только значение $V$, и оно должно соответствовать значению функции в точке $x + (n+1)h$. Вы его и получаете: $2.84 = (2 + 0.2)^2$
3. Почему столбец $V$ пустой, кроме последнего значения - затрудняюсь ответить. Возможно, какие-то особенности работы $dataGridView$. Перепишите так, чтобы в цикле писались только $i$-е значения, но не $i+1$.

Например так:

Код:
            //сохраняем нулевую строку с начальным значениями до цикла. Переменные x, h, u, V должны быть проинициализированы ранее
            chart1.Series[0].Points.AddXY(x,V);
            dataGridView1.Rows.Add();
            dataGridView1.Rows[0].Cells[0].Value = 0;
            dataGridView1.Rows[0].Cells[1].Value = x;
            dataGridView1.Rows[0].Cells[2].Value = h;
            dataGridView1.Rows[0].Cells[3].Value = f(x, u);
            dataGridView1.Rows[0].Cells[4].Value = V;

            for (int i = 1; i<n; i++) //цикл начинаем с 1. ИМХО, так удобнее
            {
                V = rk4(x, u, h); //рассчитываем следующее значение функции (оно будет i-m)
                x += h; //ПОТОМ! двигаем аргумент (теперь он тоже будет i-m)
                u = V; //сохраняем следующее значение функции в переменной u. Нужно для следующего прохода цикла.
                //все i-е значения сохраняем в структуре данных:
                chart1.Series[0].Points.AddXY(x,V);
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = i;
                dataGridView1.Rows[i].Cells[1].Value = x;
                dataGridView1.Rows[i].Cells[2].Value = h;
                dataGridView1.Rows[i].Cells[3].Value = f(x, u);
                dataGridView1.Rows[i].Cells[4].Value = V;
             }



-- 26.11.2019, 08:39 --

Кроме того, можно избавиться от переменной $V$, сейчас она тоже самое, что и $u$. Но может она Вам нужна для каких-то целей в будущем, не знаю. Если не нужна - избавляйтесь от неё.

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение26.11.2019, 08:55 


10/12/17
50
Большое спасибо. Всё работает)

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение26.11.2019, 13:33 
Экс-модератор
Аватара пользователя


23/12/05
12064
 i  Lorein_, EUgeneUS, предпочтительнее использовать тег syntax (Подсветка синтаксиса в форме ответа) вместо тега code, где это возможно. Пример ниже:


Используется синтаксис Java
                chart1.Series[0].Points.AddXY(x,V);
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = i;
                dataGridView1.Rows[i].Cells[1].Value = x;
                dataGridView1.Rows[i].Cells[2].Value = h;
                dataGridView1.Rows[i].Cells[3].Value = f(x, u);
                dataGridView1.Rows[i].Cells[4].Value = V;

 Профиль  
                  
 
 Re: Метод Рунге-Кутты 4-го порядка
Сообщение16.12.2019, 10:40 


10/12/17
50
Pphantom в сообщении #1426815 писал(а):
Ну в собственно методе Рунге-Кутты все и в самом деле верно. А вот с правилом Рунге вы творите что-то странное .

Я разобралась с правилом Рунге.Только в моменте когда $\left\lvert S \right\rvert>\varepsilon $ проведенные расчёты следует считать слишком грубыми,и расчёты нужно повторить из предыдущей точки,но с шагом $\frac{h}{2}$. А у меня в коде получается,что расчёт ведется из этой же точки. Не знаю как записать в коде расчёт из предыдущей точки.
код: [ скачать ] [ спрятать ]
Используется синтаксис C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RungeKutta
{
    public partial class Form1 : Form
    {
       
        public Form1()
        {
            InitializeComponent();
        }

        double f(double x, double u)
        {
            double L = double.Parse(textBox1.Text);
            return (-L * u);
           
        }
        double rk4(double x, double u, double h)
        {
           
            double k1, k2, k3, k4, u1;
            k1 = h * f(x, u);
            k2 = h * f(x + 0.5* h, u + 0.5 * k1);
            k3 = h * f(x + 0.5* h, u + 0.5 * k2);
            k4 = h * f(x + h, u + k3);
            u1 = u + (1.0 / 6.0) * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
            return u1;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            chart1.Series[0].Points.Clear();
            chart1.Series[1].Points.Clear();
            dataGridView1.Visible = true;
            dataGridView1.Rows.Clear();
            dataGridView1.Columns.Clear();
           
            dataGridView1.ColumnCount = 14;
           
            dataGridView1.Columns[0].HeaderText = "i";
            dataGridView1.Columns[1].HeaderText = "x";
            dataGridView1.Columns[2].HeaderText = "h";
            dataGridView1.Columns[3].HeaderText = "f(x,u)";
            dataGridView1.Columns[4].HeaderText = "V";
            dataGridView1.Columns[5].HeaderText = "Vi";
            dataGridView1.Columns[6].HeaderText = "S";
            dataGridView1.Columns[7].HeaderText = "V_точн.";
            dataGridView1.Columns[8].HeaderText = "E";
            dataGridView1.Columns[9].HeaderText = "S";
           
            double eps = double.Parse(textBox3.Text);
            double x = double.Parse(textBox5.Text);//начало интервала
            double u = double.Parse(textBox2.Text);
            double h = double.Parse(textBox4.Text);//начальный шаг
            double b = double.Parse(textBox6.Text); //конец интервала
            double L = double.Parse(textBox1.Text);
            int hmax = int.Parse(textBox7.Text);
         
           double V_2i = 0, S = 0, V = 0;

            chart1.Series[0].Points.AddXY(x, u);
            chart1.Series[1].Points.AddXY(x, Math.Exp(-L * x));
            dataGridView1.Rows.Add();
            dataGridView1.Rows[0].Cells[0].Value = 0;
            dataGridView1.Rows[0].Cells[1].Value = x;
            dataGridView1.Rows[0].Cells[2].Value = h;
            dataGridView1.Rows[0].Cells[3].Value = f(x, u);
            dataGridView1.Rows[0].Cells[4].Value = V;
            dataGridView1.Rows[0].Cells[5].Value = V_2i;
            dataGridView1.Rows[0].Cells[6].Value = S;
            dataGridView1.Rows[0].Cells[7].Value = Math.Exp(-L * x);
            dataGridView1.Rows[0].Cells[8].Value = Math.Abs(V - Math.Exp(-L * x));
            dataGridView1.Rows[0].Cells[9].Value = Math.Abs(S);
           

            for (int i = 1; i<hmax; i++)
            {
                chart1.Series[1].Points.AddXY(x, Math.Exp(-L * x));
                if (checkBox1.Checked == true)
                {
                    V = rk4(x, u, h);
                    V_2i = rk4(x, u, h / 2);
                    S = (V - V_2i) / 15;
                    if (Math.Abs(S) > eps)
                    {
                        h /= 2;
                        V = rk4(x, u, h);//Расчёт должен быть из предыдущей точки!!
                        x += h;
                        u = V;
                        if (x + h > b) break;

                    }
                    else
                        if (Math.Abs(S) < (eps /32))
                    {
                        h *= 2;
                        V = rk4(x, u, h);
                        x += h;
                        u = V;
                        if (x + h > b) break;
                    }
                    else
                    if (Math.Abs(S) >= (eps / 32) && Math.Abs(S) <= eps)
                    {
                        x += h;
                        u =V;
                        if (x + h > b) break;

                    }


                }

                if (checkBox1.Checked == false)
                {
                    V = rk4(x, u, h);
                    x += h;
                    u = V;
                    if (x + h > b) break;

                }

                chart1.Series[0].Points.AddXY(x, u);
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[0].Value = i;
                dataGridView1.Rows[i].Cells[1].Value = x;
                dataGridView1.Rows[i].Cells[2].Value = h;
                dataGridView1.Rows[i].Cells[3].Value = f(x, u);
                dataGridView1.Rows[i].Cells[4].Value = V;
                dataGridView1.Rows[i].Cells[5].Value = V_2i;
                dataGridView1.Rows[i].Cells[6].Value = S;
                dataGridView1.Rows[i].Cells[7].Value = Math.Exp(-L * x);
                dataGridView1.Rows[i].Cells[8].Value = Math.Abs(V - Math.Exp(-L * x));
                dataGridView1.Rows[i].Cells[9].Value = Math.Abs(S);


             
            }

           
        }
     
    }
}
 

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 26 ]  На страницу Пред.  1, 2

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group