Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python RK4方法和Euler方法仅适用于某些公式_Python_Numeric_Runge Kutta - Fatal编程技术网

Python RK4方法和Euler方法仅适用于某些公式

Python RK4方法和Euler方法仅适用于某些公式,python,numeric,runge-kutta,Python,Numeric,Runge Kutta,我试图写一个算法来解决非线性常微分方程 dr/dt = r(t)+r²(t) 哪个有(一种可能的)解决方案 r(t) = r²(t)/2+r³(t)/3 T0 + (Ts − T0)*exp(−kt) 为此,我在python中实现了euler方法和RK4方法。对于错误检查,我使用了rosettacode上的示例: dT/dt = -k(T(t)-T0) 解决方案 r(t) = r²(t)/2+r³(t)/3 T0 + (Ts − T0)*exp(−kt) 因此,我的代码现

我试图写一个算法来解决非线性常微分方程

dr/dt = r(t)+r²(t)  
哪个有(一种可能的)解决方案

r(t) = r²(t)/2+r³(t)/3  
T0 + (Ts − T0)*exp(−kt)
为此,我在python中实现了euler方法和RK4方法。对于错误检查,我使用了rosettacode上的示例:

dT/dt = -k(T(t)-T0)
解决方案

r(t) = r²(t)/2+r³(t)/3  
T0 + (Ts − T0)*exp(−kt)
因此,我的代码现在看起来像

import numpy as np
from matplotlib import pyplot as plt

def test_func_1(t, x):
    return x*x

def test_func_1_sol(t, x):
    return x*x*x/3.0

def test_func_2_sol(TR, T0, k, t):
    return TR + (T0-TR)*np.exp(-0.07*t)

def rk4(func, dh, x0, t0):
    k1 = dh*func(t0, x0)
    k2 = dh*func(t0+dh*0.5, x0+0.5*k1)
    k3 = dh*func(t0+dh*0.5, x0+0.5*k2)
    k4 = dh*func(t0+dh, x0+k3)
    return x0+k1/6.0+k2/3.0+k3/3.0+k4/6.0

def euler(func, x0, t0, dh):
    return x0 + dh*func(t0, x0)

def rho_test(t0, rho0):
    return rho0 + rho0*rho0

def rho_sol(t0, rho0):
    return rho0*rho0*rho0/3.0+rho0*rho0/2.0

def euler2(f,y0,a,b,h):
    t,y = a,y0
    while t <= b:
        #print "%6.3f %6.5f" % (t,y)
        t += h
        y += h * f(t,y)

def newtoncooling(time, temp):
    return -0.07 * (temp - 20)

x0 = 100
x_vec_rk = []
x_vec_euler = []
x_vec_rk.append(x0)

h = 1e-3
for i in range(100000):
    x0 = rk4(newtoncooling, h, x0, i*h)
    x_vec_rk.append(x0)

x0 = 100
x_vec_euler.append(x0)
x_vec_sol = []
x_vec_sol.append(x0)

for i in range(100000):
    x0 = euler(newtoncooling, x0, 0, h)
    #print(i, x0)
    x_vec_euler.append(x0)
    x_vec_sol.append(test_func_2_sol(20, 100, 0, i*h))

euler2(newtoncooling, 0, 0, 1, 1e-4)

x_vec = np.linspace(0, 1, len(x_vec_euler))

plt.plot(x_vec, x_vec_euler, x_vec, x_vec_sol, x_vec, x_vec_rk)
plt.show()

#rho-function
x0 = 1
x_vec_rk = []
x_vec_euler = []
x_vec_rk.append(x0)

h = 1e-3
num_steps = 650
for i in range(num_steps):
    x0 = rk4(rho_test, h, x0, i*h)
    print "%6.3f %6.5f" % (i*h, x0)
    x_vec_rk.append(x0)

x0 = 1
x_vec_euler.append(x0)
x_vec_sol = []
x_vec_sol.append(x0)

for i in range(num_steps):
    x0 = euler(rho_test, x0, 0, h)
    print "%6.3f %6.5f" % (i*h, x0)
    x_vec_euler.append(x0)
    x_vec_sol.append(rho_sol(i*h, i*h+x0))

x_vec = np.linspace(0, num_steps*h, len(x_vec_euler))
plt.plot(x_vec, x_vec_euler, x_vec, x_vec_sol, x_vec, x_vec_rk)
plt.show()
将numpy导入为np
从matplotlib导入pyplot作为plt
def测试功能1(t,x):
返回x*x
def测试功能1溶胶(t,x):
返回x*x*x/3.0
def测试功能2溶胶(TR、T0、k、t):
返回TR+(T0-TR)*np.exp(-0.07*t)
def rk4(func、dh、x0、t0):
k1=dh*func(t0,x0)
k2=dh*func(t0+dh*0.5,x0+0.5*k1)
k3=dh*func(t0+dh*0.5,x0+0.5*k2)
k4=dh*func(t0+dh,x0+k3)
返回x0+k1/6.0+k2/3.0+k3/3.0+k4/6.0
def欧拉(func、x0、t0、dh):
返回x0+dh*func(t0,x0)
def rho_测试(t0,rho):
返回rho0+rho0*rho0
def rho_sol(t0,rho0):
返回rho0*rho0*rho0/3.0+rho0*rho0/2.0
def euler2(f、y0、a、b、h):
t、 y=a,y0

而t0.65,对于RK4和euler)对于我的公式。因此,是我的实现不正确,还是我没有看到另一个错误?

搜索方程的精确解:

dr/dt = r(t)+r²(t)
我发现:

r(t) = exp(C+t)/(1-exp(C+t))
其中,
C
是取决于初始条件的任意常数。可以看出,对于
t->-C
而言,
r(t)->无穷大

我不知道你们使用什么初始条件,但在计算数值解时可能会遇到这种奇异性

更新: 由于初始条件是
r(0)=1
常数
C
C=ln(1/2)~-0.693
。它可以解释为什么数值解在t>0.65时崩溃

更新:
为了验证你的代码,你可以简单地比较你计算的数值解,比如说,
0你的方程的解是r(t)=exp(t)/(1-exp(t)),不是吗?根据*x%2Bx,它是r(t)=rho_sol()不,对于
r'(t)=t+t²是这样的。这应该会让你觉得
r(t)=r²(t)/2+r³(t)/3
是一个只有常数解的
r
的隐式方程。@RomanFursenko:我是个白痴,我在WA中输入了错误的数据……我的初始条件是x0=1,如代码中所示。你可以在初始值中求出
r(t)=(r(0)*exp(t))/(1-r(0)*(exp(t)-1))
@同样,为了验证你的代码,你可以简单地比较你的数值解,比如说
0