BVP4c solve for unknown boundary

ぐ巨炮叔叔 提交于 2020-01-07 04:20:14

问题


I am trying to use bvp4c to solve a system of 4 odes. The issue is that one of the boundaries is unknown.

Can bvp4c handle this? In my code L is the unknown I am solving for.

I get an error message printed below.

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

Unfortunately I get the following error message ;

>> 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:


One trick to transform a variable end point into a fixed one is to change the time scale. If x'(t)=f(t,x(t)) is the differential equation, set t=L*s, s from 0 to 1, and compute the associated differential equation for y(s)=x(L*s)

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

The next trick to employ is to transform the global variable into a part of the differential equation by computing it as constant function. So the new system is

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

and the value of L occurs as additional free left or right boundary value, increasing the number of variables = dimension of the state vector to the number of boundary conditions.


I do not have Matlab readily available, in Python with the tools in scipy this can be implemented as

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()

which produces

Trying different initial values for L finds other solutions on quite different scales, among them

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


来源:https://stackoverflow.com/questions/42936333/bvp4c-solve-for-unknown-boundary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!