使用此代码求解二阶微分方程

时间:2019-05-28 19:53:59

标签: python differential-equations runge-kutta

我无法编写针对我为 y'= y

编写的代码求解二阶微分方程的程序

我知道我应该编写一个程序,将一个二阶微分方程转换为两个常微分方程,但是我不知道该怎么做。

P.S。 :我必须在下面使用该代码。这是一项作业

请原谅我的错误,这是我的第一个问题。预先感谢

from pylab import*
xd=[];y=[]
def F(x,y):
    return y
def rk4(x0,y0,h,N):
    xd.append(x0)
    yd.append(y0)
    for i in range (1,N+1) :
        k1=F(x0,y0)
        k2=F(x0+h/2,y0+h/2*k1)
        k3=F(x0+h/2,y0+h/2*k2)
        k4=F(x0+h,y0+h*k3)
        k=1/6*(k1+2*k2+2*k3+k4)
        y=y0+h*k
        x=x0+h
        yd.append(y)
        xd.append(x)
        y0=y
        x0=x
    return xd,yd
x0=0
y0=1
h=0.1
N=10
x,y=rk4(x0,y0,h,N)
print("x=",x)
print("y=",y)
plot(x,y)
show()

1 个答案:

答案 0 :(得分:0)

您基本上可以将Cauchy形式的任何n阶标量ODE(常微分方程)重新格式化为1阶ODE。您在此操作中唯一要“支付”的是第二个ODE变量将是向量而不是向量标量函数。

让我给您一个ODE为2的示例。假设您的ODE为:y''= F(x,y,y')。然后,您可以将其替换为[y,y']'= [y',F(x,y,y')],在这种情况下,必须对向量的导数进行逐项理解。

让我们取回您的代码,而不是使用4阶的Runge-Kutta作为ODE的近似解决方案,我们将应用一个简单的Euler方案。

from pylab import*
import matplotlib.pyplot as plt

# we are approximating the solution of y' = f(x,y) for x in [x_0, x_1] satisfying the Cauchy condition y(x_0) = y0

def f(x, y0):
    return y0

# here f defines the equation y' = y

def explicit_euler(x0, x1, y0, N,):
    # The following formula relates h and N
    h = (x1 - x0)/(N+1)

    xd = list()
    yd = list()

    xd.append(x0)
    yd.append(y0)

    for i in range (1,N+1) :
        # We use the explicite Euler scheme y_{i+1} = y_i + h * f(x_i, y_i)
        y = yd[-1] + h * f(xd[-1], yd[-1])
        # you can replace the above scheme by any other (R-K 4 for example !)
        x = xd[-1] + h

        yd.append(y)
        xd.append(x)

    return xd, yd

N = 250
x1 = 5
x0 = 0
y0 = 1
# the only function which satisfies y(0) = 1 and y'=y is y(x)=exp(x).
xd, yd =explicit_euler(x0, x1, y0, N)
plt.plot(xd,yd)
plt.show()
# this plot has the right shape !

looks like a nice exponential function !

请注意,您可以用R-K 4替换具有更好的稳定性和收敛性的Euler方案。

现在,假设您想求解二阶ODE,例如:y''= -y,初始条件为y(0)= 1和y'(0)=0。然后必须进行变换将标量函数y转换为大小为2的向量,如上面所述和下面的代码注释中所述。

from pylab import*
import matplotlib.pyplot as plt
import numpy as np

# we are approximating the solution of y'' = f(x,y,y') for x in [x_0, x_1] satisfying the Cauchy condition of order 2:
# y(x_0) = y0 and y'(x_0) = y1

def f(x, y_d_0, y_d_1):
    return -y_d_0

# here f defines the equation y'' = -y

def explicit_euler(x0, x1, y0, y1, N,):
    # The following formula relates h and N
    h = (x1 - x0)/(N+1)

    xd = list()
    yd = list()

    xd.append(x0)
    # to allow group operations in R^2, we use the numpy library
    yd.append(np.array([y0, y1]))

    for i in range (1,N+1) :
        # We use the explicite Euler scheme y_{i+1} = y_i + h * f(x_i, y_i)
        # remember that now, yd is a list of vectors

        # the equivalent order 1 equation is [y, y']' = [y', f(x,y,y')]
        y = yd[-1] + h * np.array([yd[-1][1], f(xd[-1], yd[-1][0], yd[-1][1])])  # vector of dimension 2
        print(y)
        # you can replace the above scheme by any other (R-K 4 for example !)

        x = xd[-1] + h  # vector of dimension 1

        yd.append(y)
        xd.append(x)

    return xd, yd

x0 = 0
x1 = 30
y0 = 1
y1 = 0

# the only function satisfying y(0) = 1, y'(0) = 0 and y'' = -y is y(x) = cos(x)
N = 5000
xd, yd =explicit_euler(x0, x1, y0, y1, N)
# I only want the first variable of yd
yd_1 = list(map(lambda y: y[0], yd))

plt.plot(xd,yd_1)
plt.show()

looks like a nice cosine function !