--- title: "Model" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Model} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r cran, eval=FALSE} install.packages("PKPDsim") ``` # Introduction `new_ode_model` is the function that creates a new ODE model that can be used in the `sim()` command. It defines the ODE system and sets some attributes for the model. The model can be specified in three different ways: - `model`: a string that references a model from the library included in `PKPDsim`. Examples in the current library are e.g. `pk_1cmt_oral`, `pk_2cmt_iv`. To show the available models, run `new_ode_model()` without any arguments. - `code`: using code specifying derivatives for ODE specified in *pseudo-R* code - `file`: similar to `code`, but reads the code from a file # Model from library For example, a 1-compartment oral PK model can be obtained using: ```{r load-lib, echo=FALSE} library(PKPDsim) ``` ```{r new-model} pk1 <- new_ode_model(model = "pk_1cmt_oral") ``` Run the `new_ode_model()` function without arguments to see the currently available models: ```{r available-models, error=TRUE} new_ode_model() ``` # Custom model from code The custom model needs to be specified as a string or text block: ```{r custom-model} pk1 <- new_ode_model(code = " dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CL/V) * A[2] ") ``` The input code should adhere to the following rules: - the derivatives in the ODE system are defined using `dAdt`omputate - array indices for the derivatives and compartments are indicated with `[ ]`. Compartments indices can start at either 0 or 1. If the latter, all indices will be reduced by 1 in the translation to C++ code. - equations are defined using `=` - power functions need to be written out as `pow(base,exp)`. - force any numbers to be interpreted as `real`, to avoid them being interpreted as `integer`. So if an equation involves the real number `3`, it is usually safer to write this as `3.0` in code. The input code is translated into a C++ function. You can check that the model compiled correctly by typing the model name on the R command line, which prints the model information: ```{r print-custom-model} pk1 ``` If you're interested, you can also output the actual C++ function that is compiled by specifying the `cpp_show_code=TRUE` argument to the `new_ode_model()` function. # More custom model options You can introduce new variables in your code, but you will have to define them using `declare_variables` argument too: ```{r custom-model-variables} pk1 <- new_ode_model(code = " KEL = CL/V dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -KEL * A[2] ", declare_variables = c("KEL")) ``` Also, when you want to use covariates in your ODE system (more info on how to define covariates is in the *Covariates* vignette), you will have to define them, both in the code and in the function call: ```{r custom-model-covariates} pk1 <- new_ode_model(code = " CLi = WT/70 KEL = CLi/V dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CL*(WT/70)/V) * A[2] ", declare_variables = c("KEL", "CLi"), covariates = c("WT")) ``` One exception to the input code syntax is the definition of power functions. `PKPDsim` does not translate those from the *pseudo-R* code to valid C++ syntax automatically. C/C++ does not use the `^` to indicate power functions, but uses the `pow(value, base)` function instead, so for example an allometric PK model should be written as: ```{r custom-model-power-functions} pk1 <- new_ode_model(code = " CLi = CL * pow((WT/70), 0.75) dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CLi/V) * A[2] ", declare_variables = c("CLi")) ``` ## Dosing / bioavailability The default dosing compartment and bioavailability can be specified using the `dose` argument. By default, the dose will go into compartment `1`, with a bioavailability of `1`. The `bioav` element in the list can be either a number or a character string referring a parameter. ```{r bioav} pk1 <- new_ode_model(code = " dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CL/V) * A[2] ", dose = list(cmt = 1, bioav = "F1"), parameters = list(KA = 1, CL = 5, V = 50, F1 = 0.7) ) ``` Bioavailability can also be used for dosing based on mg/kg, since that is not supported in `new_regimen()`. The way to implement this is by scaling the dose by the "weight" covariate using the bioavailability: ```{r scale} mod <- new_ode_model(code = " dAdt[1] = -(CL/V)*A[1]; ", dose = list(cmt = 1, bioav = "WT"), obs = list(cmt = 1, scale = "V"), covariates = list("WT" = new_covariate(value = 70)) ) ``` ## Observations The observation compartment can be set by specifying a list to the `obs` argument, with either the elements `cmt` and `scale`, or `variable`. ```{r obs} pk1 <- new_ode_model(code = " dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CL/V) * A[2] ", obs = list(cmt = 2, scale = "V") ) ``` The `scale` can be either a parameter or a number, the `cmt` can only be a number. *Note that the variables specified inside the differential equation block are not available as scaling parameters. E.g. for allometry you will have to redefine the scaled volume as follows:* ```{r scale-2} pk1 <- new_ode_model(code = " Vi = V * (WT/70) dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CL/Vi) * A[2] ", obs = list(cmt = 2, scale = "V * (WT/70)") ) ``` Or define the observation using a variable: ```{r variable} pk1 <- new_ode_model(code = " dAdt[1] = -KA * A[1] dAdt[2] = +KA * A[1] -(CL/V) * A[2] CONC = A[2] ", obs = list(variable = "CONC"), declare_variables = "CONC" ) ``` # Custom model from file Using the `file` argument, the model code is read from the specified files. This is just a convenience function, i.e. it allows you to separate models from R code more easily. ```{r model-from-file, eval=FALSE} pk1 <- new_ode_model( file = "pk_1cmt_oral_nonlin_v1.txt", declare_variables = c("KEL", "CLi") ) ```