Nothing
### ============================================================================
### Interface to a generalized code for solving explicit variable and fixed
### step ODE solvers of the Runge-Kutta family, see helpfile for details.
### ============================================================================
rk <- function(y, times, func, parms, rtol = 1e-6, atol = 1e-6,
verbose = FALSE, tcrit = NULL, hmin = 0, hmax = NULL, hini = hmax,
ynames = TRUE, method = rkMethod("rk45dp7", ... ), maxsteps = 5000,
dllname = NULL, initfunc = dllname, initpar = parms,
rpar = NULL, ipar = NULL, nout = 0, outnames = NULL, forcings = NULL,
initforc = NULL, fcontrol = NULL, events = NULL, ...) {
## check for unsupported solver options
dots <- list(...); nmdots <- names(dots)
if(any(c("jacfunc", "jactype", "mf", "bandup", "banddown") %in% nmdots)) {
warning("Euler and Runge-Kutta solvers make no use of a Jacobian,\n",
" ('jacfunc', 'jactype', 'mf', 'bandup' and 'banddown' are ignored).\n")
}
if(any(c("lags") %in% nmdots)) {
warning("lags are not yet implemented for Euler and Runge-Kutta solvers,\n",
" (argument 'lags' is ignored).\n")
}
if (is.list(func)) { # a list of compiled functions
if (!is.null(initfunc) & "initfunc" %in% names(func))
stop("If 'func' is a list that contains initfunc, argument 'initfunc' should be NULL")
if (!is.null(dllname) & "dllname" %in% names(func))
stop("If 'func' is a list that contains dllname, argument 'dllname' should be NULL")
if (!is.null(initforc) & "initforc" %in% names(func))
stop("If 'func' is a list that contains initforc, argument 'initforc' should be NULL")
if (!is.null(events$func) & "eventfunc" %in% names(func))
stop("If 'func' is a list that contains eventfunc, argument 'events$func' should be NULL")
if ("eventfunc" %in% names(func)) {
if (! is.null(events))
events$func <- func$eventfunc
else
events <- list(func = func$eventfunc)
}
if (!is.null(func$initfunc)) initfunc <- func$initfunc
if (!is.null(func$dllname)) dllname <- func$dllname
if (!is.null(func$initforc)) initforc <- func$initforc
func <- func$func
}
if (is.character(method)) method <- rkMethod(method)
varstep <- method$varstep
if (!varstep & (hmin != 0 | !is.null(hmax)))
cat("'hmin' and 'hmax' are ignored (fixed step Runge-Kutta method).\n")
## Check inputs
hmax <- checkInput(y, times, func, rtol, atol,
jacfunc = NULL, tcrit, hmin, hmax, hini, dllname)
if (hmax == 0) hmax <- .Machine$double.xmax # i.e. practically unlimited
n <- length(y)
if (maxsteps < 0) stop("maxsteps must be positive")
if (!is.finite(maxsteps)) maxsteps <- .Machine$integer.max - 1
if (is.null(tcrit)) tcrit <- max(times)
## ToDo: check for nonsense-combinations of densetype and d
if (!is.null(method$densetype)) {
## make this an integer to avoid errors on the C level
method$densetype <- as.integer(method$densetype)
if (!(method$densetype %in% c(1L, 2L))) {
warning("Unknown value of densetype; set to NULL")
method$densetype <- NULL
}
}
## Checks and ajustments for Neville-Aitken interpolation
## - starting from deSolve >= 1.7 this interpolation method
## is disabled by default.
## - Dense output for special RK methods is enabled and
## all others adjust internal time steps to hit external time steps
if (is.null(method$nknots)) {
method$nknots <- 0L
} else {
method$nknots <- as.integer(ceiling(method$nknots))
}
nknots <- method$nknots
if (nknots > 8L) {
warning("Large number of nknots does not make sense.")
} else if (nknots < 2L) {
## method without or with disabled interpolation
method$nknots <- 0L
} else {
trange <- diff(range(times))
## ensure that we have at least nknots + 2 data points; + 0.5 for safety)
## to allow 3rd order polynomial interpolation
## for methods without built-in dense output
if ((is.null(method$d) & # has no "dense output"?
is.null(method$densetype) & # or no dense output type
(hmax > 1.0/(nknots + 2.5) * trange))) { # or time steps too large?
## in interpolation mode: automatic adjustment of step size arguments
## to ensure the required minimum of knots
hini <- hmax <- 1.0/(nknots + 2.5) * trange
if (hmin < hini) hmin <- hini
cat("\nNote: Method ", method$ID,
" needs intermediate steps for interpolation\n")
cat("hmax decreased to", hmax, "\n")
}
}
## Model as shared object (DLL)?
Ynames <- attr(y, "names")
Initfunc <- NULL
Eventfunc <- NULL
events <- checkevents(events, times, Ynames, dllname)
if (! is.null(events$newTimes)) times <- events$newTimes
## dummy forcings
flist <-list(fmat = 0, tmat = 0, imat = 0, ModelForc = NULL)
Nstates <- length(y) # assume length of states is correct
## function specified in a DLL or inline compiled
if (is.character(func) | inherits(func, "CFunc")) {
DLL <- checkDLL(func, NULL, dllname,
initfunc, verbose, nout, outnames)
Initfunc <- DLL$ModelInit
Func <- DLL$Func
Nglobal <- DLL$Nglobal
Nmtot <- DLL$Nmtot
Eventfunc <- events$func
if (! is.null(forcings))
flist <- checkforcings(forcings, times, dllname, initforc, verbose, fcontrol)
if (is.null(ipar)) ipar <- 0
if (is.null(rpar)) rpar <- 0
## preparation for events in R if function is a DLL (added by KS)
if (is.function(Eventfunc))
rho <- environment(Eventfunc)
else
rho <- NULL
} else {
## parameter initialisation not needed if function is not a DLL
initpar <- NULL
rho <- environment(func)
## func is overruled, either including ynames, or not
## This allows to pass the "..." arguments and the parameters
if(ynames) {
Func <- function(time, state, parms){
attr(state, "names") <- Ynames
func(time, state, parms, ...)}
if (! is.null(events$Type))
if (events$Type == 2)
Eventfunc <- function(time, state) {
attr(state, "names") <- Ynames
events$func(time, state, parms, ...)
}
} else { # no ynames...
Func <- function(time, state, parms)
func(time, state, parms, ...)
if (! is.null(events$Type))
if (events$Type == 2)
Eventfunc <- function(time, state)
events$func(time, state, parms, ...)
}
## Call func once to figure out whether and how many "global"
## results it wants to return and some other safety checks
FF <- checkFuncEuler(Func, times, y, parms, rho, Nstates)
Nglobal <- FF$Nglobal
Nmtot <- FF$Nmtot
if (! is.null(events$Type))
if (events$Type == 2) checkEventFunc(Eventfunc, times, y, rho)
}
## handle length of atol and rtol
if (Nstates %% length(atol))
warning("length of atol does not match number of states")
if (Nstates %% length(rtol))
warning("length of rtol does not match number of states")
atol <- rep(atol, length.out = Nstates)
rtol <- rep(rtol, length.out = Nstates)
## Number of steps until the solver gives up
# nsteps <- min(.Machine$integer.max -1, maxsteps * length(times))
## total number of time steps is set to
## average number per time step * number of time steps
## but not less than required for the largest time step with given hini
nsteps <- min(.Machine$integer.max - 1,
max(maxsteps * length(times), # max. total number of steps
max(diff(times))/hini + 1) # but not less than required
)
vrb <- FALSE # TRUE forces some internal debugging output of the C code
## Implicit methods
on.exit(.C("unlock_solver"))
implicit <- method$implicit
if (is.null(implicit)) implicit <- 0
if (implicit) {
if (is.null(hini)) hini <- 0
out <- .Call("call_rkImplicit", as.double(y), as.double(times),
Func, Initfunc, parms, Eventfunc, events,
as.integer(Nglobal), rho,
as.double(tcrit), as.integer(vrb),
as.double(hini), as.double(rpar), as.integer(ipar), method,
as.integer(nsteps), flist)
} else if (varstep) { # Methods with variable step size
if (is.null(hini)) hini <- hmax
out <- .Call("call_rkAuto", as.double(y), as.double(times),
Func, Initfunc, parms, Eventfunc, events,
as.integer(Nglobal), rho, as.double(atol),
as.double(rtol), as.double(tcrit), as.integer(vrb),
as.double(hmin), as.double(hmax), as.double(hini),
as.double(rpar), as.integer(ipar), method,
as.integer(nsteps), flist)
} else { # Fixed step methods
## hini = 0 for fixed step methods means
## that steps in "times" are used as they are
if (is.null(hini)) hini <- 0
out <- .Call("call_rkFixed", as.double(y), as.double(times),
Func, Initfunc, parms, Eventfunc, events,
as.integer(Nglobal), rho,
as.double(tcrit), as.integer(vrb),
as.double(hini), as.double(rpar), as.integer(ipar), method,
as.integer(nsteps), flist)
}
## output cleanup
out <- saveOutrk(out, y, n, Nglobal, Nmtot,
iin = c(1, 12:15), iout = c(1:3, 13, 18))
attr(out, "type") <- "rk"
if (verbose) diagnostics(out)
return(out)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.