tests/testthat/test-focei-lincmt-adr-default.R

# rxode2's default linCmt() sensitivity method resolves to forward-mode AD
# (linCmtSensType="auto" -> 3, "AD"; reverse mode measured slower on an
# optimized build).  nlmixr2est does not pin linCmtSensType anywhere, so a
# FOCEi fit must really take that path; the observable is which sensType
# codes linCmtB() computed a Jacobian with, and the explicit "ADr" override
# must still reach the fit.
test_that("a linCmt() FOCEi fit uses rxode2's forward-mode AD default", {
  skip_on_cran()
  skip_if_not(
    exists("linCmtBSensTypesSeen", envir = asNamespace("rxode2")),
    "rxode2 without linCmtBSensTypesSeen()"
  )
  seen <- function() utils::getFromNamespace("linCmtBSensTypesSeen", "rxode2")(TRUE)
  one.cmt <- function() {
    ini({
      tka <- 0.45
      tcl <- log(c(0, 2.7, 100))
      tv <- 3.45
      eta.ka ~ 0.6
      eta.cl ~ 0.3
      eta.v ~ 0.1
      add.sd <- 0.7
    })
    model({
      ka <- exp(tka + eta.ka)
      cl <- exp(tcl + eta.cl)
      v <- exp(tv + eta.v)
      linCmt() ~ add(add.sd)
    })
  }
  ctl <- function(st) {
    foceiControl(
      print = 0,
      maxOuterIterations = 0L,
      covMethod = "",
      calcTables = FALSE,
      rxControl = rxode2::rxControl(linCmtSensType = st)
    )
  }
  fit <- function(st) {
    invisible(seen())
    f <- suppressWarnings(suppressMessages(
      nlmixr2(one.cmt, nlmixr2data::theo_sd, est = "focei", control = ctl(st))
    ))
    list(objf = f$objf, seen = seen())
  }
  auto <- fit("auto")
  expect_true(3L %in% auto$seen)
  expect_false(31L %in% auto$seen)
  rev <- fit("ADr")
  expect_true(31L %in% rev$seen)
  expect_false(3L %in% rev$seen)
  expect_equal(auto$objf, rev$objf, tolerance = 1e-6)
})

Try the nlmixr2est package in your browser

Any scripts or data that you put into this service are public.

nlmixr2est documentation built on Sept. 20, 2026, 9:08 a.m.