---
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")
)
```