Learn R Programming

bvpSolve (version 1.1)

bvptwp: Solver for two-point boundary value problems of ordinary differential equations, using a mono-implicit Runge-Kutta formula

Description

Solves a boundary value problem of a system of ordinary differential equations. This is an implementation of the fortran code twpbvpc, based on mono-implicit Runge-Kutta formulae of orders 4, 6 and 8 in a deferred correction framework and that uses conditioning in the mesh selection.

written by J.R. Cash, F. Mazzia and M.H. Wright.

Usage

bvptwp(yini=NULL, x, func, yend=NULL, parms=NULL, guess=NULL,
  xguess=NULL, yguess=NULL, jacfunc=NULL, bound=NULL, jacbound=NULL,
  leftbc=NULL, islin=FALSE, nmax=1000, atol=1e-8, cond = FALSE,
  allpoints=TRUE, dllname=NULL, initfunc=dllname, ncomp=NULL,
  forcings=NULL, initforc = NULL, fcontrol=NULL, verbose=FALSE, ...)

Arguments

yini
either a vector with the initial (state) variable values for the ODE system, or NULL.

If yini is a vector, use NA for an initial value which is not available. If yini has a

x
sequence of the independent variable for which output is wanted; the first value of x must be the initial value (at which yini is defined), the final value the end condition (at which yend is defined).
func
either an R-function that computes the values of the derivatives in the ODE system (the model definition) at point x, or a character string giving the name of a compiled function in a dynamically loaded shared library. If
yend
either a vector with the final (state) variable values for the ODE system, or NULL;

if yend is a vector, use NA for a final value which is not available. If yend has a names<

parms
vector or a list with parameters passed to func, jacfunc, bound and jacbound (if present).
guess
guess for the value(s) of the unknown initial conditions; i.e. one value for each NA in yini. Ignored if xguess and yguess are given. The length of guess should equ
xguess
Initial grid x, a vector. bvptwp requires the length of xguess to be at least equal to the length of x. If this is not the case, then xguess and yguess will be interpola
yguess
First guess values of y, corresponding to initial grid xguess; a matrix with number of rows equal to the number of equations, and whose number of columns equals the length of xguess. if the rows of <
jacfunc
jacobian (optional) - either an R-function that evaluates the jacobian of func at point x, or a string with the name of a function or subroutine in dllname that computes the Jacobian (see vignette "
bound
boundary function (optional) - only if yini and yend are not available. Either an Rfunction that evaluates the i-th boundary element at point x, or a string with the name of a function or subroutine in
jacbound
jacobian of the boundary function (optional) - only if bound is defined. Either an Rfunction that evaluates the gradient of the i-th boundary element with respect to the state variables, at point x, or a string with t
leftbc
only if yini and yend are not available: the number of left boundary conditions.
islin
set to TRUE if the problem is linear - this will speed up the simulation.
nmax
maximal number of subintervals during the calculation.
atol
error tolerance, a scalar.
cond
if TRUE, uses conditioning in the mesh selection
allpoints
sometimes the solver estimates the solution in a number of extra points, and by default the solutions at these extra points will also be returned.

By setting allpoints equal to FALSE, only output corresponding t

dllname
a string giving the name of the shared library (without extension) that contains all the compiled function or subroutine definitions referred to in func, jacfunc, bound and jacbound. Note t
initfunc
if not NULL, the name of the initialisation function (which initialises values of parameters), as provided in dllname. See package vignette "bvpSolve".
ncomp
only used if the model is specified by compiled code, the number of components (or equations). See package vignette "bvpSolve".
forcings
only used if dllname is specified: a list with the forcing function data sets, each present as a two-columned matrix, with (time,value); interpolation outside the interval [min(times), max(times)] is done
initforc
if not NULL, the name of the forcing function initialisation function, as provided in dllname. It MUST be present if forcings has been given a value.

See package vignette "compiledCode"

fcontrol
A list of control parameters for the forcing functions.

See package vignette "compiledCode" from package deSolve.

verbose
if TRUE then more verbose output will be generated as "warnings".
...
additional arguments passed to the model functions.

Value

  • A matrix with up to as many rows as elements in x and as many columns as elements in yini or ncomp plus the number of "global" values returned from func, plus an additional column (the first) for the x-value.

    Typically, there will be one row for each element in x unless the solver returns with an unrecoverable error. In certain cases, bvptwp will return the solution also in a number of extra points. This will occur if the number of points as in x was not sufficient. In order to not return these extra points, set allpoints equal to FALSE.

    If yini has a names attribute, it will be used to label the columns of the output value. If yini is not named, the solver will try to find the names in yend, yguess and ultimately guess.

Details

This is an implementation of the method twpbvpC, written by Cash, Mazzia and Wright, to solve two-point boundary value problems of ordinary differential equations.

A boundary value problem does not have all initial values of the state variable specified. Rather some conditions are specified at the end of the integration interval. The number of unknown boundary conditions must be equal to the number of equations (or the number of dependent variables y).

The ODEs and boundary conditions are made available through the user-provided routines, func and vectors yini and yend or (optionally) bound.

The corresponding partial derivatives for func and bound are optionally available through the user-provided routines, jacfunc and jacbound. Default is that they are automatically generated by bvptwp, using numerical differences.

The user-requested tolerance is provided through tol. The default is $1e^-6$

If the function terminates because the maximum number of subintervals was exceeded, then it is recommended that 'the program be run again with a larger value for this maximum.' It may also help to start with a simple version of the model, and use its result as initial guess to solve the more complex problem (continuation strategy, see example 2, and package vignette "bvpSolve").

Models may be defined in compiled C or Fortran code, as well as in an R-function.

This is similar to the initial value problem solvers from package deSolve. See package vignette "bvpSolve" for details about writing compiled code.

The fcontrol argument is a list that can supply any of the following components (conform the definitions in the approx function): [object Object],[object Object],[object Object],[object Object] The defaults are:

fcontrol=list(method="linear", rule = 2, f = 0, ties = "ordered")

Note that only ONE specification is allowed, even if there is more than one forcing function data set.

References

J.R. Cash and M.H. Wright, A deferred correction method for nonlinear two-point boundary value problems: implementation and numerical evaluation, SIAM J. Sci. Stat. Comput., 12 (1991) 971 989.

Cash, J. R. and F. Mazzia, A new mesh selection algorithm, based on conditioning, for two-point boundary value codes. J. Comput. Appl. Math. 184 (2005), no. 2, 362--381.

http://www.ma.ic.ac.uk/~jcash/BVP_software

See Also

bvpshoot for the shooting method

Examples

Run this code
## =============================================================================
## Example 1: simple standard problem
## solve the BVP ODE:
## d2y/dt^2=-3py/(p+t^2)^2
## y(t= -0.1)=-0.1/sqrt(p+0.01)
## y(t=  0.1)= 0.1/sqrt(p+0.01)
## where p = 1e-5
##
## analytical solution y(t) = t/sqrt(p + t^2).
##
## The problem is rewritten as a system of 2 ODEs:
## dy=y2
## dy2=-3p*y/(p+t^2)^2
## =============================================================================

#--------------------------------
# Derivative function
#--------------------------------
fun <- function(t,y,pars)
{ dy1 <-y[2]
  dy2 <- - 3*p*y[1]/(p+t*t)^2
  return(list(c(dy1,
             dy2))) }


# parameter value
p    <-1e-5

# initial and final condition; second conditions unknown
init <- c(y=-0.1/sqrt(p+0.01), dy=NA)
end  <- c(0.1/sqrt(p+0.01), NA)

# Solve bvp
sol  <- as.data.frame(bvptwp(yini=init,x=seq(-0.1,0.1,by=0.001),
        func=fun, yend=end, guess=1))
plot(sol$x,sol$y,type="l")

# add analytical solution
curve(x/sqrt(p+x*x),add=TRUE,type="p")

## =============================================================================
## Example 1b: simple
## solve d2y/dx2 + 1/x*dy/dx + (1-1/(4x^2)y = sqrt(x)*cos(x),
## on the interval [1,6] and with boundary conditions:
## y(1)=1, y(6)=-0.5
##
## Write as set of 2 odes
## dy/dx = y2
## dy2/dx  = - 1/x*dy/dx - (1-1/(4x^2)y + sqrt(x)*cos(x)
## =============================================================================

f2 <- function(x,y,parms)
{
 dy  <- y[2]
 dy2 <- -1/x*y[2]-(1-1/(4*x^2))*y[1] + sqrt(x)*cos(x)
 list(c(dy,dy2))
}

x    <- seq(1,6,0.1)
sol  <- bvptwp(yini=c(y=1,dy=NA),yend=c(-0.5,NA),x=x,func=f2,guess=1)
plot(sol,which="y")

# add the analytic solution
curve(0.0588713*cos(x)/sqrt(x)+1/4*sqrt(x)*cos(x)+0.740071*sin(x)/sqrt(x)+
      1/4*x^(3/2)*sin(x),add=TRUE,type="l")

## =============================================================================
## Example 2  - using continuation
## Problem nr 24 from http://www.ma.ic.ac.uk/~jcash/BVP_software/PROBLEMS.PDF
## xi*A*y*y'' -((1+ga)/2-xi*A'*y*y'+y'/y+(A'/A*(1-(ga-1)/2*y^2)=0
## where A = 1 + x2, y(x=0) = 0:9129, y(x=1) = 0:375
## =============================================================================

Prob24 <- function(x, y, pars, xi) {
  A <- 1+x*x
  AA <- 2*x
  ga <- 1.4
  list(c(y[2],
       (((1+ga)/2 -xi*AA)*y[1]*y[2]-y[2]/y[1]-
       (AA/A)*(1-(ga-1)*y[1]^2/2))/(xi*A*y[1])  ))
}

ini <- c(0.9129,NA)
end <- c(0.375,NA)

# This problem needs an initial guess for y; (as it divides by y,
# the default, 0, does not work)

# guess of y; set equal to 1
xguess <- c(0,1)
yguess <- matrix(nrow=2,ncol=2,data=1)

# start with relatively large value of xi
xi <-0.01
print(system.time(
mod1  <- bvptwp(yini=ini,yend=end,x=seq(0,1,by=0.01),
        func=Prob24,xi=xi, xguess=xguess,yguess=yguess)
))        
plot(mod1[,1:2], ylim = c(0.4,1.4), type="l", lwd=2)

# use previous solution to initialise solver for smaller xi
xi <-0.005
mod1b  <- bvptwp(yini=ini,yend=end,x=seq(0,1,by=0.01),
        func=Prob24,xi=xi, xguess=mod1[,1],yguess=t(mod1[,2:3]))
lines(mod1b, lwd=2, col="red")


## =============================================================================
## Example 3  - solved with specification of boundary, and jacobians
## d4y/dx4 =R(dy/dx*d2y/dx2 -y*dy3/dx3)
## y(0)=y'(0)=0
## y(1)=1, y'(1)=0
##
## dy/dx  = y2
## dy2/dx = y3    (=d2y/dx2)
## dy3/dx = y4    (=d3y/dx3)
## dy4/dx = R*(y2*y3 -y*y4)
## =============================================================================

f2<- function(x,y,parms,R)
{
  list(c(y[2],y[3],y[4],R*(y[2]*y[3]-y[1]*y[4]) ))
}

df2 <- function(x,y,parms,R)
{
 df <- matrix(nr=4,nc=4,byrow=TRUE,data=c(
             0,1,0,0,
             0,0,1,0,
             0,0,0,1,
             -1*R*y[4],R*y[3],R*y[2],-R*y[1]))
}

g2 <- function(i,y,parms,R)
{
  if ( i ==1) return(y[1])
  if ( i ==2) return(y[2])
  if ( i ==3) return(y[1]-1)
  if ( i ==4) return(y[2])
}

dg2 <- function(i,y,parms,R)
{
  if ( i ==1) return(c(1,0,0,0))
  if ( i ==2) return(c(0,1,0,0))
  if ( i ==3) return(c(1,0,0,0))
  if ( i ==4) return(c(0,1,0,0))
}

require(bvpSolve)
init <- c(1,NA)
R    <- 0.01
sol  <- bvptwp(x=seq(0,1,by=0.01), leftbc=2,
        func=f2, guess=1,R=R,
        bound=g2, jacfunc=df2, jacbound=dg2)
plot(sol[,1:2])  # columns do not have names

mf <- par ("mfrow")
sol  <- bvptwp(x=seq(0,1,by=0.01), leftbc=2,
        func=f2, guess=c(y=1,dy=1,dy2=1,dy3=1),R=R,
        bound=g2, jacfunc=df2, jacbound=dg2)
plot(sol)        # here they do
par(mfrow=mf)

Run the code above in your browser using DataLab