bundles / scipy latest / scipy / integrate / _bvp / solve_bvp
function
scipy.integrate._bvp:solve_bvp
source: /scipy/integrate/_bvp.py :712
Signature
def solve_bvp ( fun , bc , x , y , p = None , S = None , fun_jac = None , bc_jac = None , tol = 0.001 , max_nodes = 1000 , verbose = 0 , bc_tol = None ) Summary
Solve a boundary value problem for a system of ODEs.
Extended Summary
This function numerically solves a first order system of ODEs subject to two-point boundary conditions
dy / dx = f(x, y, p) + S * y / (x - a), a <= x <= b bc(y(a), y(b), p) = 0
Here x is a 1-D independent variable, y(x) is an n-D vector-valued function and p is a k-D vector of unknown parameters which is to be found along with y(x). For the problem to be determined, there must be n + k boundary conditions, i.e., bc must be an (n + k)-D function.
The last singular term on the right-hand side of the system is optional. It is defined by an n-by-n matrix S, such that the solution must satisfy S y(a) = 0. This condition will be forced during iterations, so it must not contradict boundary conditions. See [2] for the explanation how this term is handled when solving BVPs numerically.
Problems in a complex domain can be solved as well. In this case, y and p are considered to be complex, and f and bc are assumed to be complex-valued functions, but x stays real. Note that f and bc must be complex differentiable (satisfy Cauchy-Riemann equations [4]), otherwise you should rewrite your problem for real and imaginary parts separately. To solve a problem in a complex domain, pass an initial guess for y with a complex data type (see below).
Parameters
fun: callableRight-hand side of the system. The calling signature is
fun(x, y), orfun(x, y, p)if parameters are present. All arguments are ndarray:xwith shape (m,),ywith shape (n, m), meaning thaty[:, i]corresponds tox[i], andpwith shape (k,). The return value must be an array with shape (n, m) and with the same layout asy.bc: callableFunction evaluating residuals of the boundary conditions. The calling signature is
bc(ya, yb), orbc(ya, yb, p)if parameters are present. All arguments are ndarray:yaandybwith shape (n,), andpwith shape (k,). The return value must be an array with shape (n + k,).x: array_like, shape (m,)Initial mesh. Must be a strictly increasing sequence of real numbers with
x[0]=aandx[-1]=b.y: array_like, shape (n, m)Initial guess for the function values at the mesh nodes, ith column corresponds to
x[i]. For problems in a complex domain passywith a complex data type (even if the initial guess is purely real).p: array_like with shape (k,) or None, optionalInitial guess for the unknown parameters. If None (default), it is assumed that the problem doesn't depend on any parameters.
S: array_like with shape (n, n) or NoneMatrix defining the singular term. If None (default), the problem is solved without the singular term.
fun_jac: callable or None, optionalFunction computing derivatives of f with respect to y and p. The calling signature is
fun_jac(x, y), orfun_jac(x, y, p)if parameters are present. The return must contain 1 or 2 elements in the following order:df_dyarray_like with shape (n, n, m), where an element (i, j, q) equals to d f_i(x_q, y_q, p) / d (y_q)_j.
df_dparray_like with shape (n, k, m), where an element (i, j, q) equals to d f_i(x_q, y_q, p) / d p_j.
Here q numbers nodes at which x and y are defined, whereas i and j number vector components. If the problem is solved without unknown parameters, df_dp should not be returned.
If
fun_jacis None (default), the derivatives will be estimated by the forward finite differences.bc_jac: callable or None, optionalFunction computing derivatives of bc with respect to ya, yb, and p. The calling signature is
bc_jac(ya, yb), orbc_jac(ya, yb, p)if parameters are present. The return must contain 2 or 3 elements in the following order:dbc_dyaarray_like with shape (n, n), where an element (i, j) equals to d bc_i(ya, yb, p) / d ya_j.
dbc_dybarray_like with shape (n, n), where an element (i, j) equals to d bc_i(ya, yb, p) / d yb_j.
dbc_dparray_like with shape (n, k), where an element (i, j) equals to d bc_i(ya, yb, p) / d p_j.
If the problem is solved without unknown parameters, dbc_dp should not be returned.
If
bc_jacis None (default), the derivatives will be estimated by the forward finite differences.tol: float, optionalDesired tolerance of the solution. If we define
r = y' - f(x, y), where y is the found solution, then the solver tries to achieve on each mesh intervalnorm(r / (1 + abs(f)) < tol, wherenormis estimated in a root mean squared sense (using a numerical quadrature formula). Default is 1e-3.max_nodes: int, optionalMaximum allowed number of the mesh nodes. If exceeded, the algorithm terminates. Default is 1000.
verbose: {0, 1, 2}, optionalLevel of algorithm's verbosity:
0 (default)work silently.
1display a termination report.
2display progress during iterations.
bc_tol: float, optionalDesired absolute tolerance for the boundary condition residuals:
bcvalue should satisfyabs(bc) < bc_tolcomponent-wise. Equals totolby default. Up to 10 iterations are allowed to achieve this tolerance.
Returns
: Bunch object with the following fields defined:sol: PPolyFound solution for y as scipy.interpolate.PPoly instance, a C1 continuous cubic spline.
p: ndarray or None, shape (k,)Found parameters. None, if the parameters were not present in the problem.
x: ndarray, shape (m,)Nodes of the final mesh.
y: ndarray, shape (n, m)Solution values at the mesh nodes.
yp: ndarray, shape (n, m)Solution derivatives at the mesh nodes.
rms_residuals: ndarray, shape (m - 1,)RMS values of the relative residuals over each mesh interval (see the description of
tolparameter).niter: intNumber of completed iterations.
status: intReason for algorithm termination:
0: The algorithm converged to the desired accuracy.
1: The maximum number of mesh nodes is exceeded.
2: A singular Jacobian encountered when solving the collocation system.
message: stringVerbal description of the termination reason.
success: boolTrue if the algorithm converged to the desired accuracy (
status=0).
Notes
This function implements a 4th order collocation algorithm with the control of residuals similar to [1]. A collocation system is solved by a damped Newton method with an affine-invariant criterion function as described in [3].
Note that in [1] integral residuals are defined without normalization by interval lengths. So, their definition is different by a multiplier of h**0.5 (h is an interval length) from the definition used here.
Array API Standard Support
solve_bvp has experimental support for Python Array API Standard compatible backends in addition to NumPy. Please consider testing these features by setting an environment variable SCIPY_ARRAY_API=1 and providing CuPy, PyTorch, JAX, or Dask arrays as array arguments. The following combinations of backend and device (or other capability) are supported.
==================== ==================== ==================== Library CPU GPU ==================== ==================== ==================== NumPy ✅ n/a CuPy n/a ⛔ PyTorch ⛔ ⛔ JAX ⛔ ⛔ Dask ⛔ n/a ==================== ==================== ====================
See
dev-arrayapifor more information.
Examples
In the first example, we solve Bratu's problem:: y'' + k * exp(y) = 0 y(0) = y(1) = 0 for k = 1. We rewrite the equation as a first-order system and implement its right-hand side evaluation:: y1' = y2 y2' = -exp(y1)import numpy as np def fun(x, y): return np.vstack((y[1], -np.exp(y[0])))✓
def bc(ya, yb): return np.array([ya[0], yb[0]])✓
x = np.linspace(0, 1, 5)
✓y_a = np.zeros((2, x.size)) y_b = np.zeros((2, x.size)) y_b[0] = 3✓
from scipy.integrate import solve_bvp res_a = solve_bvp(fun, bc, x, y_a) res_b = solve_bvp(fun, bc, x, y_b)✓
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] import matplotlib.pyplot as plt✓
plt.plot(x_plot, y_plot_a, label='y_a') plt.plot(x_plot, y_plot_b, label='y_b') plt.legend() plt.xlabel("x") plt.ylabel("y")✗
plt.show()
✓
def fun(x, y, p): k = p[0] return np.vstack((y[1], -k**2 * y[0]))✓
def bc(ya, yb, p): k = p[0] return np.array([ya[0], yb[0], ya[1] - k])✓
x = np.linspace(0, 1, 5) y = np.zeros((2, x.size)) y[0, 1] = 1 y[0, 3] = -1✓
sol = solve_bvp(fun, bc, x, y, p=[6])
✓sol.p[0]
✗x_plot = np.linspace(0, 1, 100) y_plot = sol.sol(x_plot)[0]✓
plt.plot(x_plot, y_plot) plt.xlabel("x") plt.ylabel("y")✗
plt.show()
✓
Aliases
-
scipy.integrate.solve_bvp