diff options
| author | Johannes Ranke <jranke@uni-bremen.de> | 2015-04-16 10:03:02 +0200 | 
|---|---|---|
| committer | Johannes Ranke <jranke@uni-bremen.de> | 2015-04-16 10:03:02 +0200 | 
| commit | 10fb9aac470d87afbe2d4ee9e3d1898bfc3f1aa7 (patch) | |
| tree | a1ee701046f3ccc69a05eb9e5461cf8167e3ddda | |
| parent | d34e5c053794a08cc73c9042ccccfb334ae0f62d (diff) | |
| parent | 7f5455e1a49f44a0fa341ee7cca86dfb03e273a2 (diff) | |
Merge branch 'compile_odes'
| -rw-r--r-- | DESCRIPTION | 6 | ||||
| -rw-r--r-- | NAMESPACE | 3 | ||||
| -rw-r--r-- | R/mkinmod.R | 34 | ||||
| -rw-r--r-- | R/mkinpredict.R | 22 | ||||
| -rw-r--r-- | man/mkinfit.Rd | 6 | 
5 files changed, 57 insertions, 14 deletions
| diff --git a/DESCRIPTION b/DESCRIPTION index 03976d1e..0eaf6ebf 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: mkin  Type: Package  Title: Routines for Fitting Kinetic Models with One or More State    Variables to Chemical Degradation Data -Version: 0.9-35 +Version: 0.9-36  Date: 2015-02-20  Authors@R: c(person("Johannes", "Ranke", role = c("aut", "cre", "cph"),                       email = "jranke@uni-bremen.de"), @@ -13,11 +13,13 @@ Description: Calculation routines based on the FOCUS Kinetics Report (2006).    Includes a function for conveniently defining differential equation models,    model solution based on eigenvalues if possible or using numerical solvers    and a choice of the optimisation methods made available by the FME package. +  If the ccSolve package and a C compiler is available, differential equation +  models are solved as compiled C functions.    Please note that no warranty is implied for correctness of results or fitness    for a particular purpose.  Depends: minpack.lm, rootSolve  Imports: FME, deSolve -Suggests: knitr, RUnit +Suggests: knitr, RUnit, ccSolve  License: GPL  LazyLoad: yes  LazyData: yes @@ -9,5 +9,6 @@ import(    FME,    deSolve,    minpack.lm, -  rootSolve +  rootSolve, +  ccSolve  ) diff --git a/R/mkinmod.R b/R/mkinmod.R index d04f811f..37cd02b4 100644 --- a/R/mkinmod.R +++ b/R/mkinmod.R @@ -36,6 +36,9 @@ mkinmod <- function(..., use_of_ff = "min", speclist = NULL)    # differential equations (if supported), parameter names and a mapping from
    # model variables to observed variables. If possible, a matrix representation
    # of the differential equations is included
 +  # Compiling the functions from the C code generated below using the ccSolve package
 +  # only works if the implicit assumption about differential equations specified below
 +  # is satisfied
    parms <- vector()
    # }}}
 @@ -269,6 +272,37 @@ mkinmod <- function(..., use_of_ff = "min", speclist = NULL)      model$coefmat <- m
    }#}}}
 +  # Create a function compiled from C code if possible #{{{
 +  if (require(ccSolve)) {
 +    diffs.C <- paste(diffs, collapse = ";\n")
 +    diffs.C <- paste0(diffs.C, ";")
 +    for (i in seq_along(diffs)) {
 +      obs_var <- names(diffs)[i]
 +
 +      # Replace d_... terms by f[i-1]
 +      # First line
 +      pattern <- paste0("^d_", obs_var)
 +      replacement <- paste0("\nf[", i - 1, "]")
 +      diffs.C <- gsub(pattern, replacement, diffs.C)
 +      # Other lines
 +      pattern <- paste0("\\nd_", obs_var)
 +      replacement <- paste0("\nf[", i - 1, "]")
 +      diffs.C <- gsub(pattern, replacement, diffs.C)
 +
 +      # Replace names of observed variables by y[i],
 +      # making the implicit assumption that the observed variables only occur after "* "
 +      pattern <- paste0("\\* ", obs_var)
 +      replacement <- paste0("* y[", i - 1, "]")
 +      diffs.C <- gsub(pattern, replacement, diffs.C)
 +    }
 +    # Unfortunately, the models with time occuring in the diffs do not compile
 +    if (sum(sapply(spec, function(x) x$type %in% c("SFO", "SFORB"))) == length(spec)) {
 +      message("Compiling differential equation model from auto-generated C code...")
 +      model$compiled <- compile.ode(diffs.C, language = "C", parms = parms)
 +    }
 +  }
 +  # }}}
 +
    class(model) <- "mkinmod"
    return(model)
  }
 diff --git a/R/mkinpredict.R b/R/mkinpredict.R index da013d50..bed82441 100644 --- a/R/mkinpredict.R +++ b/R/mkinpredict.R @@ -87,17 +87,21 @@ mkinpredict <- function(mkinmod, odeparms, odeini,      names(out) <- c("time", mod_vars)    }     if (solution_type == "deSolve") { -    mkindiff <- function(t, state, parms) { +    if (!is.null(mkinmod$compiled)) { +       mkindiff <- mkinmod$compiled +     } else { +       mkindiff <- function(t, state, parms) { -      time <- t -      diffs <- vector() -      for (box in names(mkinmod$diffs)) -      { -        diffname <- paste("d", box, sep="_")       -        diffs[diffname] <- with(as.list(c(time, state, parms)), -          eval(parse(text=mkinmod$diffs[[box]]))) +        time <- t +        diffs <- vector() +        for (box in names(mkinmod$diffs)) +        { +          diffname <- paste("d", box, sep="_")       +          diffs[diffname] <- with(as.list(c(time, state, parms)), +            eval(parse(text=mkinmod$diffs[[box]]))) +        } +        return(list(c(diffs)))        } -      return(list(c(diffs)))      }       out <- ode(        y = odeini, diff --git a/man/mkinfit.Rd b/man/mkinfit.Rd index 9c82f5ff..4b0ad1a7 100644 --- a/man/mkinfit.Rd +++ b/man/mkinfit.Rd @@ -235,7 +235,8 @@ SFO_SFO <- mkinmod(    parent = list(type = "SFO", to = "m1", sink = TRUE),    m1 = list(type = "SFO"))  # Fit the model to the FOCUS example dataset D using defaults -fit <- mkinfit(SFO_SFO, FOCUS_2006_D) +fit <- mkinfit(SFO_SFO, FOCUS_2006_D, solution_type = "eigen") +fit.deSolve <- mkinfit(SFO_SFO, FOCUS_2006_D, solution_type = "deSolve")  summary(fit)  # Use stepwise fitting, using optimised parameters from parent only fit, FOMC @@ -258,10 +259,10 @@ SFORB_SFO <- mkinmod(    m1 = list(type = "SFO"))  # Fit the model to the FOCUS example dataset D using defaults  fit.SFORB_SFO <- mkinfit(SFORB_SFO, FOCUS_2006_D) +fit.SFORB_SFO.deSolve <- mkinfit(SFORB_SFO, FOCUS_2006_D, solution_type = "deSolve")  # Use starting parameters from parent only SFORB fit (not really needed in this case)  fit.SFORB = mkinfit(SFORB, FOCUS_2006_D)  fit.SFORB_SFO <- mkinfit(SFORB_SFO, FOCUS_2006_D, parms.ini = fit.SFORB$bparms.ode) -}  # Weighted fits, including IRLS  SFO_SFO.ff <- mkinmod(parent = list(type = "SFO", to = "m1"), @@ -275,6 +276,7 @@ summary(f.w.mean)  f.w.mean.irls <- mkinfit(SFO_SFO.ff, FOCUS_2006_D, weight = "mean",                           reweight.method = "obs")  summary(f.w.mean.irls) +}  \dontrun{  # Manual weighting | 
