bvpFiniteDifference¶
Solves a (parameterized) system of differential equations with boundary conditions at two points, using a variable order, variable step size finite difference method with deferred corrections.
Synopsis¶
bvpFiniteDifference (fcneq, fcnjac, fcnbc, n, nleft, ncupbc, tleft, tright, linear, nfinal, tfinal, yfinal)
Required Arguments¶
- void
fcneq(n,t,y[],p,dydt[]) (Input) - User supplied function to evaluate derivatives.
- int
n(Input) - Number of differential equations.
- float
t(Input) - Independent variable, t.
- float
y[](Input) - Array of size
ncontaining the dependent variable values, y(t). - float
p(Input) - Continuation parameter, p. See optional argument
problemEmbedded. - float
dydt[](Output) - Array of size
ncontaining the derivatives y′(t). - void
fcnjac(n,t,y[],p,dypdy[]) (Input) - User supplied function to evaluate the Jacobian.
- int
n(Input) - Number of differential equations.
- float
t(Input) - Independent variable, t.
- float
y[](Input) - Array of size
ncontaining the dependent variable values, y(t). - float
p(Input) - Continuation parameter, p. See optional argument
problemEmbedded. - float
dypdy[[]](Output) nbynarray containing the partial derivatives \(a_{i,j} = \partial f_i ⁄ \partial y_j\) evaluated at \((t, y)\). The values \(a_{i,j}\) are returned indypdy[(i-1)\*n+(j-1)].- void
fcnbc(n,yleft[],yright[],p,h[]) (Input) - User supplied function to evaluate the boundary conditions.
- int
n(Input) - Number of differential equations.
- float
yleft[](Input) - Array of size
ncontaining the values of the dependent variable at the left endpoint. - float
yright[](Input) - Array of size
ncontaining the values of the dependent variable at the right endpoint. - float
p(Input) - Continuation parameter, p See optional argument
problemEmbedded. - float
h[](Output) - Array of size
ncontaining the boundary condition residuals. The boundary conditions are defined by \(h_i = 0\), for i = 0, …,n-1. The left endpoint conditions must be defined first, then, the conditions involving both endpoints, and finally the right endpoint conditions. - int
n(Input) - Number of differential equations.
- int
nleft(Input) - Number of initial conditions. The value
nleftmust be greater than or equal to zero and less thann. - int
ncupbc(Input) - Number of coupled boundary conditions. The value
nleft+ncupbcmust be greater than zero and less than or equal ton. - float
tleft(Input) - The left endpoint.
- float
tright(Input) - The right endpoint.
- int
linear(Input) - Integer flag to indicate if the differential equations and the boundary
conditions are linear. Set
linearto one if the differential equations and the boundary conditions are linear, otherwise setlinearto zero. - int
nfinal(Output) - Number of final grid points, including the endpoints.
- float
tfinal(Output) - Array of size
mxgridcontaining the final grid points. Only the firstnfinalpoints are significant. See optional argumentmaxSubinterfor definition ofmxgrid. - float
yfinal(Output) - Array of size
mxgridbyncontaining the values ofYat the points intfinal. See optional argumentmaxSubinterfor definition ofmxgrid.
Optional Arguments¶
tol, float (Input)Relative error control parameter. The computations stop when
\[\begin{split}\begin{array}{l} \left|E_{i,j}\right| / \max\left(y_{i,j},1.0\right) < \mathit{tol} \text{ for all } i = 0, n = 1 \text{, and } j = 0, \mathit{ngrid}-1 \\ \text{Here } E_{i,j} \text{ is the estimated error on } y_{i,j} \end{array}\end{split}\]Default:
tol= .001.initialStepsize, intninit, floattinit[], floatyinit[[]], (Input)Initial gridpoints. Number of initial grid points, including the endpoints, is given by
ninit.tinitis an array of sizeninitcontaining the initial grid points.yinitis an array sizeninitbyncontaining an initial guess for the values ofYat the points intinit.Default:
ninit= 10,tinit[*] equally spaced in the interval [tleft,tright], andyinit[*][*] = 0.t_print, int (Input)- Parameter indicating the desired output level.
| t_print | Action |
|---|---|
| 0 | No output printed. |
| 1 | Intermediate output is printed. Default: |
maxSubinter, int (Input)Maximum number of grid points allowed.
Default:
mxgrid= 100.problemEmbedded, floatpistep, voidfcnpeq(), voidfcnpbc()If this optional argument is supplied, then the function
bvpFiniteDifferenceassumes that the user has embedded the problem into a one-parameter family of problems:\[h(\mathit{yleft}, \mathit{yright}, p) = 0\]\[y' = y'(t,y,p)\]such that for \(p = 0\) the problem is simple. For \(p = 1\), the original problem is recovered. The function
bvpFiniteDifferenceautomatically attempts to increment from \(p = 0\) to \(p = 1\). The valuepistepis the beginning increment used in this continuation. The increment will usually be changed by functionbvpFiniteDifference, but an arbitrary minimum of 0.01 is imposed.The argument
pis the initial increment size for p. The functionsfcnpeqandfcnpbcare user-supplied functions, and are defined:- void
fcnpeq(n,t,y[],p,dypdp[]) (Input) - User supplied function to evaluate the derivative of y′ with respect to the parameter p.
- int
n(Input) - Number of differential equations.
- float
t(Input) - Independent variable, t.
- float
y[](Input) - Array of size
ncontaining the dependent variable values. - float
p(Input) - Continuation parameter, p.
- float
dypdp[](Output) - Array of size
ncontaining the derivative y′ with respect to the parameter p at (t, y). - void
fcnpbc(n,yleft[],yright[],p,h[])(Input) - User supplied function to evaluate the derivative of the boundary conditions with respect to the parameter p.
- int
n(Input) - Number of differential equations.
- float
yleft[](Input) - Array of size
ncontaining the values of the dependent variable at the left endpoint. - float
yright[](Input) - Array of size
ncontaining the values of the dependent variable at the right endpoint. - float
p(Input) - Continuation parameter, p.
- float
h[](Output) - Array of size
ncontaining the derivative of \(f_i\) with respect to p. errEst(Output)- An array of size
ncontaining estimated error in y.
Description¶
The function bvpFiniteDifference is based on the subprogram PASVA3
by M. Lentini and V. Pereyra (see Pereyra 1978). The basic discretization is
the trapezoidal rule over a nonuniform mesh. This mesh is chosen adaptively,
to make the local error approximately the same size everywhere. Higher-order
discretizations are obtained by deferred corrections. Global error estimates
are produced to control the computation. The resulting nonlinear algebraic
system is solved by Newton’s method with step control. The linearized system
of equations is solved by a special form of Gauss elimination that preserves
the sparseness.
Examples¶
Example 1¶
This example solves the third-order linear equation
subject to the boundary conditions \(y(0) = y(2\pi)\) and \(y'(0) =
y'(2\pi) = 1\). (Its solution is \(y = \sin t\).) To use
bvpFiniteDifference, the problem is reduced to a system of first-order
equations by defining \(y_1= y\), \(y_2 = y'\) and \(y_3 = y''\).
The resulting system is
Note that there is one boundary condition at the left endpoint \(t = 0\) and one boundary condition coupling the left and right endpoints. The final boundary condition is at the right endpoint. The total number of boundary conditions must be the same as the number of equations (in this case 3).
from __future__ import print_function
from numpy import *
from pyimsl.math.bvpFiniteDifference import bvpFiniteDifference
def fcneqn(n, t, y, p, dydt):
dydt[0] = y[1]
dydt[1] = y[2]
dydt[2] = 2 * y[2] - y[1] + y[0] + sin(t)
def fcnjac(n, t, y, p, dfdy):
dfdy[0 * n + 0] = 0 # df1/dy1
dfdy[1 * n + 0] = 0 # df2/dy1
dfdy[2 * n + 0] = 1 # df3/dy1
dfdy[0 * n + 1] = 1 # df1/dy2
dfdy[1 * n + 1] = 0 # df2/dy2
dfdy[2 * n + 1] = -1 # df3/dy2
dfdy[0 * n + 2] = 0 # df1/dy3
dfdy[1 * n + 2] = 1 # df2/dy3
dfdy[2 * n + 2] = 2 # df3/dy3
def fcnbc(n, yleft, yright, p, h):
h[0] = yleft[1] - 1
h[1] = yleft[0] - yright[0]
h[2] = yright[1] - 1
n = 3
nleft = 1
ncupbc = 1
tleft = 0
tright = 2.0 * pi
linear = 1
yfinal = []
tfinal = []
errest = []
nfinal = []
bvpFiniteDifference(fcneqn, fcnjac, fcnbc,
n, nleft, ncupbc, tleft, tright,
linear, nfinal, tfinal, yfinal,
errEst=errest)
print(" tfinal y0 y1 y2")
for i in range(0, nfinal[0]):
print("%5d%15.6e%15.6e%15.6e%15.6e"
% (i, tfinal[i], yfinal[i][0], yfinal[i][1], yfinal[i][2]))
print("Error estimates %15.6e%15.6e%15.6e"
% (errest[0], errest[1], errest[2]))
Output¶
tfinal y0 y1 y2
0 0.000000e+00 -1.123288e-04 1.000000e+00 6.245272e-05
1 3.490659e-01 3.419106e-01 9.397087e-01 -3.419580e-01
2 6.981317e-01 6.426907e-01 7.660918e-01 -6.427229e-01
3 1.396263e+00 9.847531e-01 1.737334e-01 -9.847452e-01
4 2.094395e+00 8.660529e-01 -4.998746e-01 -8.660057e-01
5 2.792527e+00 3.421830e-01 -9.395473e-01 -3.420649e-01
6 3.490659e+00 -3.417232e-01 -9.396112e-01 3.418946e-01
7 4.188790e+00 -8.656880e-01 -5.000588e-01 8.658733e-01
8 4.886922e+00 -9.845794e-01 1.734568e-01 9.847519e-01
9 5.585054e+00 -6.427722e-01 7.658257e-01 6.429527e-01
10 5.934119e+00 -3.420820e-01 9.395433e-01 3.423986e-01
11 6.283185e+00 -1.123288e-04 1.000000e+00 6.742588e-04
Error estimates 2.839365e-04 1.792030e-04 5.585375e-04
Example 2¶
In this example, the following nonlinear problem is solved:
with \(y(0) = y(\pi) = 0\). Its solution is \(y = \sin t\). As in Example 1, this equation is reduced to a system of first-order differential equations by defining \(y_1 = y\) and \(y_2 = y'\). The resulting system is
In this problem, there is one boundary condition at the left endpoint and one at the right endpoint; there are no coupled boundary conditions.
from __future__ import print_function
from numpy import *
from pyimsl.math.bvpFiniteDifference import bvpFiniteDifference
def fcneqn(n, t, y, p, dydt):
sx = sin(t)
dydt[0] = y[1]
dydt[1] = y[0] * y[0] * y[0] - (sx * sx + 1) * sx
def fcnjac(n, t, y, p, dfdy):
dfdy[0 * n + 0] = 0 # df1/dy1
dfdy[1 * n + 0] = 3 * y[0] * y[0] # df2/dy1
dfdy[0 * n + 1] = 1 # df1/dy2
dfdy[1 * n + 1] = 0 # df2/dy2
def fcnbc(n, yleft, yright, p, h):
h[0] = yleft[0]
h[1] = yright[0]
n = 2
mxgrid = 100
ninit = 12
nleft = 1
ncupbc = 0
linear = 0
tleft = 0
tright = pi
tinit = zeros((ninit), dtype='double')
yinit = zeros((ninit, n), dtype='double')
tfinal = []
yfinal = []
errest = []
step = (tright - tleft) / (ninit - 1)
nfinal = []
for i in range(0, ninit):
tinit[i] = tleft + i * step
yinit[i][0] = 0.4 * (tinit[i] - tleft) * (tright - tinit[i])
yinit[i][1] = 0.4 * (tright + tleft - 2 * tinit[i])
hinit = {"tinit": tinit, "yinit": yinit}
bvpFiniteDifference(fcneqn, fcnjac, fcnbc,
n, nleft, ncupbc, tleft, tright,
linear, nfinal, tfinal, yfinal,
hinit=hinit, errEst=errest)
print(" t y0 y1")
for i in range(0, nfinal[0]):
print("%5d%15.6e%15.6e%15.6e"
% (i, tfinal[i], yfinal[i][0], yfinal[i][1]))
print("Error estimates %15.6e%15.6e"
% (errest[0], errest[1]))
Output¶
t y0 y1
0 0.000000e+00 0.000000e+00 9.999277e-01
1 2.855993e-01 2.817682e-01 9.594315e-01
2 5.711987e-01 5.406458e-01 8.412407e-01
3 8.567980e-01 7.557380e-01 6.548903e-01
4 1.142397e+00 9.096185e-01 4.154530e-01
5 1.427997e+00 9.898143e-01 1.423308e-01
6 1.713596e+00 9.898143e-01 -1.423308e-01
7 1.999195e+00 9.096185e-01 -4.154530e-01
8 2.284795e+00 7.557380e-01 -6.548903e-01
9 2.570394e+00 5.406458e-01 -8.412407e-01
10 2.855993e+00 2.817682e-01 -9.594315e-01
11 3.141593e+00 0.000000e+00 -9.999277e-01
Error estimates 3.906276e-05 7.123602e-05
Example 3¶
In this example, the following nonlinear problem is solved:
with \(y(0) = y(1) = \pi/2\). As in the previous examples, this equation is reduced to a system of first-order differential equations by defining \(y_1 = y\) and \(y_2 = y'\). The resulting system is
The problem is embedded in a family of problems by introducing the parameter p and by changing the second differential equation to
At \(p = 0\), the problem is linear; and at \(p = 1\), the original
problem is recovered. The derivatives \(\partial y' \partial p\) must now
be specified in the subroutine fcnpeq. The derivatives \(\partial f
/ \partial p\) are zero in fcnpbc.
from __future__ import print_function
from numpy import *
from pyimsl.math.bvpFiniteDifference import bvpFiniteDifference
def fcneqn(n, t, y, p, dydt):
z = t - 0.5
dydt[0] = y[1]
dydt[1] = p * y[0] * y[0] * y[0] + 40. / \
9. * pow(z * z, 1. / 3.) - pow(z, 8)
def fcnjac(n, t, y, p, dfdy):
dfdy[0 * n + 0] = 0 # df0/dy0
dfdy[0 * n + 1] = 1 # df0/dy1
dfdy[1 * n + 0] = 3. * (p) * (y[0] * y[0]) # df1/dy0
dfdy[1 * n + 1] = 0 # df1/dy1
def fcnbc(n, yleft, yright, p, h):
pi2 = pi / 2.0
h[0] = yleft[0] - pi2
h[1] = yright[0] - pi2
def fcnpeq(n, t, y, p, dfdp):
dfdp[0] = 0
dfdp[1] = y[0] * y[0] * y[0]
def fcnpbc(n, yleft, yright, p, dhdp):
dhdp[0] = 0
dhdp[1] = 0
n = 2
mxgrid = 45
nleft = 1
ncupbc = 0
tleft = 0
tright = 1
pistep = 0.1
linear = 0
ninit = 5
tinit = [0., 0.4, 0.5, 0.6, 1.0]
yinit = array([[0.15749, 0.00215],
[0.0, 0.00215],
[0.15749, -0.83995],
[-0.05745, 0.0],
[0.05745, 0.83995]])
tfinal = []
yfinal = []
errest = []
nfinal = []
hinit = {"tinit": tinit, "yinit": yinit}
problem_embedded = {"pistep": pistep, "fcnpeq": fcnpeq,
"fcnpbc": fcnpbc}
bvpFiniteDifference(fcneqn, fcnjac, fcnbc, n, nleft,
ncupbc, tleft, tright, linear,
nfinal, tfinal, yfinal,
maxSubinter=mxgrid,
problemEmbedded=problem_embedded,
hinit=hinit,
errEst=errest)
print(" t y0 y1")
for i in range(0, nfinal[0]):
print("%5d%15.6e%15.6e%15.6e"
% (i, tfinal[i], yfinal[i][0], yfinal[i][1]))
print("Error estimates %15.6e%15.6e"
% (errest[0], errest[1]))
Output¶
t y0 y1
0 0.000000e+00 1.570796e+00 -1.949336e+00
1 4.444444e-02 1.490495e+00 -1.669566e+00
2 8.888889e-02 1.421951e+00 -1.419465e+00
3 1.333333e-01 1.363953e+00 -1.194307e+00
4 2.000000e-01 1.294526e+00 -8.958462e-01
5 2.666667e-01 1.243627e+00 -6.373191e-01
6 3.333333e-01 1.208785e+00 -4.135207e-01
7 4.000000e-01 1.187783e+00 -2.219352e-01
8 4.250000e-01 1.183038e+00 -1.584200e-01
9 4.500000e-01 1.179822e+00 -9.973150e-02
10 4.625000e-01 1.178748e+00 -7.233901e-02
11 4.750000e-01 1.178007e+00 -4.638254e-02
12 4.812500e-01 1.177756e+00 -3.399767e-02
13 4.875000e-01 1.177582e+00 -2.205550e-02
14 4.937500e-01 1.177480e+00 -1.061179e-02
15 5.000000e-01 1.177447e+00 -1.566963e-07
16 5.062500e-01 1.177480e+00 1.061148e-02
17 5.125000e-01 1.177582e+00 2.205519e-02
18 5.187500e-01 1.177756e+00 3.399736e-02
19 5.250000e-01 1.178007e+00 4.638223e-02
20 5.375000e-01 1.178748e+00 7.233870e-02
21 5.500000e-01 1.179822e+00 9.973120e-02
22 5.750000e-01 1.183038e+00 1.584197e-01
23 6.000000e-01 1.187783e+00 2.219349e-01
24 6.666667e-01 1.208786e+00 4.135205e-01
25 7.333333e-01 1.243628e+00 6.373189e-01
26 8.000000e-01 1.294526e+00 8.958459e-01
27 8.666667e-01 1.363953e+00 1.194307e+00
28 9.111111e-01 1.421951e+00 1.419465e+00
29 9.555556e-01 1.490495e+00 1.669566e+00
30 1.000000e+00 1.570796e+00 1.949336e+00
Error estimates 3.452906e-06 5.550646e-05
Fatal Errors¶
IMSL_STOP_USER_FCN |
Request from user supplied function to stop algorithm. User flag = “#”.. |