Speed

The simulation backend in PKPDsim uses an ODE solver written in C++ (Boost::odeint) to make sure simulations are fast. Therefore, for most simulation problems computational speed will not be an issue. Even simulating thousands (or millions) of patients for complex models will rarely take more than a few minutes. Simpler simulation problems will commonly take seconds to complete.

However, in some special cases speed could become an issue, and for that it is important to understand the structure of PKPDsim’s main function (sim()) because. The sim() function is composed of three parts:

  1. preprocessing (R)
  2. looping over subjects, solving ODE for each subject (R/C++)
  3. post-processing (R)

From this structure it is easy to understand that when you would request simulation of 1,000 patients:

dat <- sim(ode = mod, ...., n = 1000)

the pre- and post-processing parts will take relatively minor computational time, since the main part will be the loop simulating the PK for the subjects. However, if instead you would write a loop yourself to simulate 1,000 patients, and would call sim() repeatedly:

dat <- c()
for(i in 1:1000) {
    dat <- rbindlist(dat, sim(ode = mod, ...., n = 1))
}

now in each iteration also the pre- and post-processing functionality would be invoked, and the overall simulation will take much longer than before, probably by an order of magnitude. The same concept applies if you would use sim() in the context of population (NLME) or individual (MAP) estimation, or in optimal design in evaluation of the FIM.

There is a different way to solve ODEs with PKPDsim though, which uses only the core ODE solver function and does not perform pre-/post-processing. If you need to use PKPDsim in an iterative context as described above, you should therefore use the sim_core() function instead, and perform the pre- and post-processing outside of the main loop, e.g.:

design <- sim(mod = mod, ...., return_design=TRUE)
dat <- c()
for(i in 1:1000) {
    dat <- rbindlist(dat, sim_core(design = design, ode = mod))
}
# potentially any post-processing here

Comparison with other packages

Several other open source R packages provide similar features as PKPDsim, the main ones being RxODE (now renamed to rxode2) and mrgsolve.

In the rxode2 package, the overhead from pre- and post-processing is separated from the main simulation function by default, while mrgsolve is more similar to PKPDsim with the overhead being included within the main simulation function. Therefore, especially when used in an iterative context, RxODE will seem much faster than PKDPsim and mrgsolve, while PKPDsim and mrgsolve will seem broadly similar. However, when using the sim_core() function as outlined above, our benchmarks indicate that simulation speed for PKDDsim is highly similar to that obtained with the RxODE package.