2017-07-02 62 views
2

我有一个3个微分方程组(从我认为的代码中可以看出)具有3个边界条件。我设法在MATLAB中用一个循环来解决这个问题,如果它要返回一个错误,那么一点一点地改变最初的猜测而不终止程序。不过,在scipysolve_bvp,我总是得到一些的答案,虽然是错的。所以我一直在改变我的猜测(它不断改变答案),并且对我从实际解决方案中得到的数据给出了非常接近的数字,但它仍然不起作用。也许还有其他一些代码问题,由于它不起作用?我刚刚编辑了他们的文档代码。用scipy解决一个BVP solve_bvp

import numpy as np 
def fun(x, y): 
    return np.vstack((3.769911184e12*np.exp(-19846/y[1])*(1-y[0]), 0.2056315191*(y[2]-y[1])+6.511664773e14*np.exp(-19846/y[1])*(1-y[0]), 1.696460033*(y[2]-y[1]))) 
def bc(ya, yb): 
    return np.array([ya[0], ya[1]-673, yb[2]-200]) 
x = np.linspace(0, 1, 5) 
#y = np.ones((3, x.size)) 
y = np.array([[1, 1, 1, 1, 1], [670, 670, 670, 670, 670], [670, 670, 670, 670, 670] ]) 
from scipy.integrate import solve_bvp 
sol = solve_bvp(fun, bc, x, y) 

实际的解决方案如下图所示。

MATLAB解法BVP

回答

1

显然,你需要一个更好的初始猜测,否则solve_bvp使用迭代方法可以y[1],使表达exp(-19846/y[1])溢出创造价值。发生这种情况时,算法可能会失败。该表达式中的溢出意味着y[1]中的某个值为负值;即解算器在杂草中如此之远以至于它很少有机会收敛到正确的解决方案。你会看到警告,有时候这个函数仍然会返回一个合理的解决方案,但是通常当溢出发生时它会返回垃圾。

您可以通过检查sol.status来确定solve_bvp是否收敛失败。如果它不是0,则失败。 sol.message包含描述状态的文本消息。

我能够用它来创建最初的猜测得到了Matlab的解决方案:的n

n = 25 
x = np.linspace(0, 1, n) 
y = np.array([x, np.full_like(x, 673), np.linspace(800, 200, n)]) 

较小的值也行,但是当n太小,溢出的警告可能会出现。

这里是我的脚本的修改版本,之后的情节,它产生:

import numpy as np 
from scipy.integrate import solve_bvp 
import matplotlib.pyplot as plt 


def fun(x, y): 
    t1 = np.exp(-19846/y[1])*(1 - y[0]) 
    dy21 = y[2] - y[1] 
    return np.vstack((3.769911184e12*t1, 
         0.2056315191*dy21 + 6.511664773e14*t1, 
         1.696460033*dy21)) 

def bc(ya, yb): 
    return np.array([ya[0], ya[1] - 673, yb[2] - 200]) 


n = 25 
x = np.linspace(0, 1, n) 
y = np.array([x, np.full_like(x, 673), np.linspace(800, 200, n)]) 

sol = solve_bvp(fun, bc, x, y) 

if sol.status != 0: 
    print("WARNING: sol.status is %d" % sol.status) 
print(sol.message) 

plt.subplot(2, 1, 1) 
plt.plot(sol.x, sol.y[0], color='#801010', label='$y_0(x)$') 
plt.grid(alpha=0.5) 
plt.legend(framealpha=1, shadow=True) 
plt.subplot(2, 1, 2) 
plt.plot(sol.x, sol.y[1], '-', color='C0', label='$y_1(x)$') 
plt.plot(sol.x, sol.y[2], '--', color='C0', label='$y_2(x)$') 
plt.xlabel('$x$') 
plt.grid(alpha=0.5) 
plt.legend(framealpha=1, shadow=True) 
plt.show() 

plot

+1

有没有办法知道,如果这是真正的* *的答案吗?就像在MATLAB中,如果我有错误的开始猜测,我会得到一个错误,但在这里一切都给了我*一些*答案。所以我现在才知道如何验证我的解决方案在Python中是对还是错。我假设没有错误消息,如溢出警告意味着它的工作。我只是用'np.linspace(700,400,n)])'尝试过,它似乎也失败了。我想我需要把变量的范围有些封闭? –

+0

*“我刚刚尝试过使用np.linspace(700,400,n)])”*这不是必需的,它当然不能保证收敛,但传递满足的初始猜测似乎是个好主意边界条件。 –

+0

谢谢。这是验证它的好方法。 你使用'y [2]'初始猜测作为一个从800到200的空间数组,而不是相反的方向,因为这是怎么回事,对吗?你为什么不为'y [1]'做一个600以上的空间,而只是使用'full_like'呢? 'y [2]'更敏感,你是如何知道的? –

相关问题