如何通过Runge-Kutta 4传递硬编码微分方程 [英] How to pass a hard coded differential equation through Runge-Kutta 4

查看:103
本文介绍了如何通过Runge-Kutta 4传递硬编码微分方程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现Runge-Kutta的示例问题 dy/dt = y-t ^ 2 +1和dy/dt = t * y + t ^ 3在C#中,我似乎无法获得期望的输出.我已将程序分为几个类,以尝试分别查看工作.我认为我的主要错误来自尝试使用委托将方法作为变量传递给Runge-Kutta进程.

I'm trying to implement Runge-Kutta for example problems dy/dt = y - t^2 + 1 and dy/dt = t * y + t^3 in C# and I cannot seem to get the output I'm expecting. I have split my program into several classes to try and look at the work individually. I think that my main error is coming from trying to pass a method through the Runge-Kutta process as a variable using a delegate.

方程类:

namespace RK4
{
    public class Eqn
    {
        double t;
        double y;
        double dt;
        double b;
        public Eqn(double t, double y, double dt, double b)
        {
            this.t = t;
            this.y = y;
            this.dt = dt;
            this.b = b;
        }
        public void Run1()
        {
            double temp;
            int step = 1;
            RK4 n = new RK4();
            while (t < b)
                    {
                        temp = n.Runge(t, y, dt, FN1);
                        y = temp;
                        Console.WriteLine("At step number {0}, t: {1}, y: {2}", step, t, y);
                        t = t + dt;
                        step++;
                    }
        }
        public void Run2()
        {
            int step = 1;
            RK4 m = new RK4();
            while (t < b)
            {
                y = m.Runge(t, y, dt, FN2);
                Console.WriteLine("At step number {0}, t: {1}, y: {2}", step, t, y);
                t = t + dt;
                step++;
            }
        }
        public static double FN1(double t, double y)
        {
            double x = y - Math.Pow(t, 2) + 1;
            return x;
        }
        public static double FN2(double t, double y)
        {
            double x = t * y + Math.Pow(t, 3);
            return x;
        }
    }
}

然后是Runge-Kutta 4课:

Then Runge-Kutta 4 Class:

    namespace RK4
    {
        class RK4
        {
            public delegate double Calc(double t, double y);
            public double Runge(double t, double y, double dt, Calc yp)
            {
                double k1 = dt * yp(t, y);
                double k2 = dt * yp(t + 0.5 * dt, y + k1 * 0.5 * dt);
                double k3 = dt * yp(t + 0.5 * dt, y + k2 * 0.5 * dt);
                double k4 = dt * yp(t + dt, y + k3 * dt);
                return (y + (1 / 6) * (k1 + 2 * k2 + 2 * k3 + k4));
            }
        }
    }

And my Program Class:

namespace RK4
{
    class Program
    {
            static void Main(string[] args)
        {
            RunProgram();
        }
        public static void RunProgram()
        {
            Console.WriteLine("*******************************************************************************");
            Console.WriteLine("************************** Fourth Order Runge-Kutta ***************************");
            Console.WriteLine("*******************************************************************************");
            Console.WriteLine("\nWould you like to implement the fourth-order Runge-Kutta on:");
            string Fn1 = "y' = y - t^2 + 1";
            string Fn2 = "y' = t * y + t^3";
            Console.WriteLine("1) {0}", Fn1);
            Console.WriteLine("2) {0}", Fn2);
            Console.WriteLine("Please enter 1 or 2");
            switch (Int32.Parse(Console.ReadLine()))
            {
                case 1:
                    Console.WriteLine("\nPlease enter beginning of the interval (a):");
                    double a = Double.Parse(Console.ReadLine());
                    Console.WriteLine("Please enter end of the interval (b):");
                    double b = Double.Parse(Console.ReadLine());
                    Console.WriteLine("Please enter the step size (h) to be used:");
                    double h = Double.Parse(Console.ReadLine());
                    Console.WriteLine("Please enter the inital conditions to satisfy y({0}) = d",a);
                    Console.WriteLine("d = ");
                    double d = Double.Parse(Console.ReadLine());
                    Console.Clear();
                    Console.WriteLine("Using the interval [{0},{1}] and step size of {2} and the inital condition of y({3}) = {4}:", a, b, h, a, d);
                    Console.WriteLine("With equation: {0}", Fn1);
                    Eqn One = new Eqn(a, d, h, b);
                    One.Run1();
                    Console.WriteLine("Press enter to exit.");
                    Console.ReadLine();
                    Environment.Exit(1);
                    break;
                case 2:
                    Console.WriteLine("\nPlease enter beginning of the interval (a):");
                    a = Double.Parse(Console.ReadLine());
                    Console.WriteLine("Please enter end of the interval (b):");
                    b = Double.Parse(Console.ReadLine());
                    Console.WriteLine("Please enter the step size (h) to be used:");
                    h = Double.Parse(Console.ReadLine());
                    Console.WriteLine("Please enter the inital conditions to satisfy y({0}) = d",a);
                    Console.WriteLine("d = ");
                    d = Double.Parse(Console.ReadLine());
                    Console.Clear();
                    Console.WriteLine("Using the interval [{0},{1}] and step size of {2} and the inital condition of y({3}) = {4}:", a, b, h, a, d);
                    Console.WriteLine("With equation: {0}", Fn1);
                    Eqn Two = new Eqn(a, d, h, b);
                    Two.Run2();
                    Console.WriteLine("Press enter to exit.");
                    Console.ReadLine();
                    Environment.Exit(1);
                    break;
                default:
                    Console.WriteLine("Improper input, please press enter to exit.");
                    Console.ReadLine();
                    Environment.Exit(1);
                    break;
            }
        }
    }
}

无论如何这都不是优雅的编程,但是我没有工作的知识来知道我现在在做什么错.从我的阅读中,我认为RK4类中的委托将能够通过我的硬编码diff eq.

This is not elegant programming by any means but I don't have the working knowledge to know what I'm doing wrong at this point. From what I was reading I thought that the delegate within the RK4 class would be able to pass through my hard coded diff eq.

推荐答案

您在RK4实现中犯了一个经典错误:使用两个变体来定位要乘以dt的乘法,您将同时使用这两个.

You are doing a classical error in the RK4 implementation: Having two variants to position the multiplication with dt to choose from, you are using both.

k2 = dt*f(t+0.5*dt, y+0.5*k1)

k2 = f(t+0.5*dt, y+0.5*dt*k1)

并类似地在该算法的其他行中.

and analogously in the other lines of the algorithm.

这篇关于如何通过Runge-Kutta 4传递硬编码微分方程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆