From 548b67e5d54e78150cfc6474ad129af9408f4997 Mon Sep 17 00:00:00 2001 From: Johannes Ranke Date: Tue, 23 Jun 2015 11:17:27 +0200 Subject: Hopefully fix compiling on Solaris, verbose option - Only declare the time variable in the C code when needed in the derivatives. - Add the option to show verbose output of cfunction() when compiling the model to a shared library. --- NEWS.md | 6 +++++- R/mkinmod.R | 34 +++++++++++++++++++++++----------- man/mkinmod.Rd | 13 +++++++++++-- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/NEWS.md b/NEWS.md index c9f7efe8..840aaade 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,7 +3,11 @@ ## MINOR CHANGES - `vignettes/compiled_models.html`: Show the performance improvement factor actually obtained when building the vignette, as well as mkin version, some system info and the CPU model used for building the vignette. -- `GNUMakefile`,`vignettes/*`: Clean up vignette generation and include table of contents in HTML vignettes +- `GNUMakefile`,`vignettes/*`: Clean up vignette generation and include table of contents in HTML vignettes. + +## BUG FIXES + +- `mkinmod.R()`: When generating the C code for the derivatives, only declare the time variable when it is needed and remove the '-W-no-unused-variable' compiler flag as the C compiler used in the CRAN checks on Solaris does not know it. # CHANGES in mkin VERSION 0.9-36 diff --git a/R/mkinmod.R b/R/mkinmod.R index 72c4652a..27716899 100644 --- a/R/mkinmod.R +++ b/R/mkinmod.R @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License along with # this program. If not, see }}} -mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) +mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE, verbose = FALSE) { if (is.null(speclist)) spec <- list(...) else spec <- speclist @@ -273,11 +273,12 @@ mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) model$coefmat <- m }#}}} - # Create a function compiled from C code if more than one observed {{{ + # Try to create a function compiled from C code if more than one observed {{{ # variable and gcc is available if (length(obs_vars) > 1) { if (Sys.which("gcc") != "") { + # Translate the R code for the derivatives to C code diffs.C <- paste(diffs, collapse = ";\n") diffs.C <- paste0(diffs.C, ";") @@ -313,10 +314,18 @@ mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) diffs.C <- gsub(pattern, replacement, diffs.C) } - if (!quiet) message("Compiling differential equation model from auto-generated C code...") + derivs_sig <- signature(n = "integer", t = "numeric", y = "numeric", + f = "numeric", rpar = "numeric", ipar = "integer") + + # Declare the time variable in the body of the function if it is used + derivs_code <- if (spec[[1]]$type %in% c("FOMC", "DFOP", "HS")) { + paste0("double time = *t;\n", diffs.C) + } else { + diffs.C + } + # Define the function initializing the parameters npar <- length(parms) - initpar_code <- paste0( "static double parms [", npar, "];\n", paste0("#define ", parms, " parms[", 0:(npar - 1), "]\n", collapse = ""), @@ -326,14 +335,17 @@ mkinmod <- function(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) " odeparms(&N, parms);\n", "}\n\n") - derivs_code <- paste0("double time = *t;\n", diffs.C) - derivs_sig <- signature(n = "integer", t = "numeric", y = "numeric", - f = "numeric", rpar = "numeric", ipar = "integer") + # Try to build a shared library + cf <- try(cfunction(list(func = derivs_sig), derivs_code, + otherdefs = initpar_code, + verbose = verbose, + convention = ".C", language = "C"), + silent = TRUE) - model$cf <- cfunction(list(func = derivs_sig), derivs_code, - otherdefs = initpar_code, - cppargs = "-Wno-unused-variable", - convention = ".C", language = "C") + if (!inherits(cf, "try-error")) { + if (!quiet) message("Successfully compiled differential equation model from auto-generated C code.") + model$cf <- cf + } } } # }}} diff --git a/man/mkinmod.Rd b/man/mkinmod.Rd index f6a8fe5d..35372919 100644 --- a/man/mkinmod.Rd +++ b/man/mkinmod.Rd @@ -13,7 +13,7 @@ in the FOCUS and NAFTA guidance documents are used. } \usage{ -mkinmod(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) +mkinmod(..., use_of_ff = "min", speclist = NULL, quiet = FALSE, verbose = FALSE) } \arguments{ \item{...}{ @@ -45,6 +45,10 @@ mkinmod(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) \item{quiet}{ Should messages be suppressed? } + \item{verbose}{ + If \code{TRUE}, passed to \code{\link{cfunction}} if applicable to give + detailed information about the C function being built. + } } \value{ A list of class \code{mkinmod} for use with \code{\link{mkinfit}}, containing @@ -80,7 +84,7 @@ mkinmod(..., use_of_ff = "min", speclist = NULL, quiet = FALSE) # Specify the SFO model (this is not needed any more, as we can now mkinfit("SFO", ...) SFO <- mkinmod(parent = list(type = "SFO")) -# One parent compound, one metabolite, both single first order. +# One parent compound, one metabolite, both single first order SFO_SFO <- mkinmod( parent = mkinsub("SFO", "m1"), m1 = mkinsub("SFO")) @@ -90,6 +94,11 @@ SFO_SFO <- mkinmod( parent = list(type = "SFO", to = "m1"), m1 = list(type = "SFO")) +# Show details of creating the C function +SFO_SFO <- mkinmod( + parent = mkinsub("SFO", "m1"), + m1 = mkinsub("SFO"), verbose = TRUE) + # If we have several parallel metabolites # (compare tests/testthat/test_synthetic_data_for_UBA_2014.R) m_synth_DFOP_par <- mkinmod(parent = mkinsub("DFOP", c("M1", "M2")), -- cgit v1.2.1