BVP4c解决未知边界问题

时间:2017-03-21 19:20:45

标签: matlab ode

我正在尝试使用bvp4c来解决4颂歌系统。问题是其中一个边界是未知的。

bvp4c可以处理吗?在我的代码中,L是我正在解决的未知数。

我收到下面打印的错误消息。

function mat4bvp
L = 8;
solinit = bvpinit(linspace(0,L,100),@mat4init);
sol = bvp4c(@mat4ode,@mat4bc,solinit);
sint = linspace(0,L);
Sxint = deval(sol,sint);
end

% ------------------------------------------------------------
function dtdpdxdy = mat4ode(s,y,L)
Lambda = 0.3536;
dtdpdxdy = [y(2)
            -sin(y(1)) + Lambda*(L-s)*cos(y(1))
            cos(y(1))
            sin(y(1))];
end
% ------------------------------------------------------------
function res = mat4bc(ya,yb,L)
res = [  ya(1) 
         ya(2)
         ya(3)
         ya(4)
        yb(1)];
end
% ------------------------------------------------------------
function yinit = mat4init(s)
yinit = [  cos(s)
    0
    0
    0
      ];
end

不幸的是我收到以下错误消息;

>> mat4bvp
Not enough input arguments.

Error in mat4bvp>mat4ode (line 13)
            -sin(y(1)) + Lambda*(L-s)*cos(y(1))

Error in bvparguments (line 105)
    testODE = ode(x1,y1,odeExtras{:});

Error in bvp4c (line 130)
    bvparguments(solver_name,ode,bc,solinit,options,varargin);

Error in mat4bvp (line 4)
sol = bvp4c(@mat4ode,@mat4bc,solinit);

1 个答案:

答案 0 :(得分:1)

将可变终点转换为固定终点的一个技巧是改变时间尺度。如果x'(t)=f(t,x(t))是微分方程,请将t=L*ss0设置为1,并计算y(s)=x(L*s)的相关微分方程

y'(s)=L*x'(L*s)=L*f(L*s,y(s))

采用的下一个技巧是将全局变量转换为微分方程的一部分,将其计算为常数函数。所以新系统是

[ y'(s), L'(s) ] = [ L(s)*f(L(s)*s,y(s)), 0 ]

并且L的值作为附加的自由左或右边界值出现,增加变量的数量=状态向量的维度到边界条件的数量。

我没有Matlab随时可用,在Python中使用scipy中的工具,这可以实现为

from math import sin, cos
import numpy as np
from scipy.integrate import solve_bvp, odeint
import matplotlib.pyplot as plt

 # The original function with the interval length as parameter

def fun0(t, y, L):
    Lambda = 0.3536;
    #print t,y,L
    return np.array([ y[1], -np.sin(y[0]) + Lambda*(L-t)*np.cos(y[0]), np.cos(y[0]), np.sin(y[0]) ]);

# Wrapper function to apply both tricks to transform variable interval length to a fixed interval.

def fun1(s,y):
    L = y[-1];
    dydt = np.zeros_like(y);
    dydt[:-1] = L*fun0(L*s, y[:-1], L);
    return dydt;

# Implement evaluation of the boundary condition residuals:

def bc(ya, yb):
    return [  ya[0],ya[1], ya[2], ya[3], yb[0] ];

# Define the initial mesh with 5 nodes:

x = np.linspace(0, 1, 3)

# This problem has multiple solutions. Try two initial guesses.

L_a=8
L_b=9

y_a = odeint(lambda y,t: fun1(t,y), [0,0,0,0,L_a], x)
y_b = odeint(lambda y,t: fun1(t,y), [0,0,0,0,L_b], x)

# Now we are ready to run the solver.

res_a = solve_bvp(fun1, bc, x, y_a.T)
res_b = solve_bvp(fun1, bc, x, y_b.T)

L_a = res_a.sol(0)[-1]
L_b = res_b.sol(0)[-1]
print "L_a=%.8f, L_b=%.8f" % ( L_a,L_b )

# Plot the two found solutions. The solution are in a spline form, use this to produce a smooth plot.

x_plot = np.linspace(0, 1, 100)
y_plot_a = res_a.sol(x_plot)[0]
y_plot_b = res_b.sol(x_plot)[0]

plt.plot(L_a*x_plot, y_plot_a, label='L=%.8f'%L_a)
plt.plot(L_b*x_plot, y_plot_b, label='L=%.8f'%L_b)
plt.legend()
plt.xlabel("t")
plt.ylabel("y")
plt.grid(); plt.show()

产生

enter image description here

L尝试不同的初始值会找到其他非常不同的解决方案,其中包括

L=0.03195111
L=0.05256775
L=0.05846539
L=0.06888907
L=0.08231966
L=4.50411522
L=6.84868060
L=20.01725616
L=22.53189063