2014 dxdy logo

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

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




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


11/12/16
14485
уездный город Н
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
12068
EUgeneUS, аргументы, скармливаемые rk4() между вторым и третьим вызовом меняются.

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


11/12/16
14485
уездный город Н
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
14485
уездный город Н
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
14485
уездный город Н
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
12068
 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, Супермодераторы



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

Сейчас этот форум просматривают: Geen


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

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