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
n
containing the dependent variable values, y(t). - float
p
(Input) - Continuation parameter, p. See optional argument
problemEmbedded
. - float
dydt[]
(Output) - Array of size
n
containing 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
n
containing the dependent variable values, y(t). - float
p
(Input) - Continuation parameter, p. See optional argument
problemEmbedded
. - float
dypdy[[]]
(Output) n
byn
array 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
n
containing the values of the dependent variable at the left endpoint. - float
yright[]
(Input) - Array of size
n
containing 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
n
containing 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
nleft
must be greater than or equal to zero and less thann
. - int
ncupbc
(Input) - Number of coupled boundary conditions. The value
nleft
+ncupbc
must 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
linear
to one if the differential equations and the boundary conditions are linear, otherwise setlinear
to zero. - int
nfinal
(Output) - Number of final grid points, including the endpoints.
- float
tfinal
(Output) - Array of size
mxgrid
containing the final grid points. Only the firstnfinal
points are significant. See optional argumentmaxSubinter
for definition ofmxgrid
. - float
yfinal
(Output) - Array of size
mxgrid
byn
containing the values ofY
at the points intfinal
. See optional argumentmaxSubinter
for 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
.tinit
is an array of sizeninit
containing the initial grid points.yinit
is an array sizeninit
byn
containing an initial guess for the values ofY
at 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
bvpFiniteDifference
assumes 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
bvpFiniteDifference
automatically attempts to increment from \(p = 0\) to \(p = 1\). The valuepistep
is 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
p
is the initial increment size for p. The functionsfcnpeq
andfcnpbc
are 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
n
containing the dependent variable values. - float
p
(Input) - Continuation parameter, p.
- float
dypdp[]
(Output) - Array of size
n
containing 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
n
containing the values of the dependent variable at the left endpoint. - float
yright[]
(Input) - Array of size
n
containing the values of the dependent variable at the right endpoint. - float
p
(Input) - Continuation parameter, p.
- float
h[]
(Output) - Array of size
n
containing the derivative of \(f_i\) with respect to p. errEst
(Output)- An array of size
n
containing 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 = “#”.. |