diff --git a/DESCRIPTION b/DESCRIPTION
index 0bb57e46..023ee7b6 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
Type: Package
Package: mrgsolve
Title: Simulate from ODE-Based Models
-Version: 1.5.1.9001
+Version: 1.5.1.9002
Authors@R:
c(person(given = "Kyle T", family = "Baron",
role = c("aut", "cre"),
diff --git a/Makefile b/Makefile
index 590bc859..8b803501 100644
--- a/Makefile
+++ b/Makefile
@@ -78,6 +78,7 @@ readme:
doc:
Rscript -e "roxygen2::roxygenize()"
+.PHONY: build
build:
R CMD build --md5 $(PKGDIR) --no-manual
diff --git a/NAMESPACE b/NAMESPACE
index 64b41012..1430f355 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -22,6 +22,7 @@ S3method(handle_spec_block,specBLOCK)
S3method(handle_spec_block,specCAPTURE)
S3method(handle_spec_block,specCMT)
S3method(handle_spec_block,specCMTN)
+S3method(handle_spec_block,specEVENT)
S3method(handle_spec_block,specFIXED)
S3method(handle_spec_block,specINCLUDE)
S3method(handle_spec_block,specINIT)
diff --git a/R/Aaaa.R b/R/Aaaa.R
index 1d6ea302..9bfee4d2 100644
--- a/R/Aaaa.R
+++ b/R/Aaaa.R
@@ -80,7 +80,7 @@ block_list <- c("ENV", "PROB", "PARAM", "INIT",
"PKMODEL", "PLUGIN", "INCLUDE", "NAMESPACE",
"OMEGA", "SIGMA", "SET","GLOBAL", "CAPTURE",
"PREAMBLE", "PRED", "BLOCK", "TRANSIT", "YAML", "NMEXT",
- "INPUT")
+ "INPUT", "EVENT")
Reserved_cvar <- c("SOLVERTIME","table","ETA","EPS", "AMT", "CMT",
"ID", "TIME", "EVID","simeps", "self", "simeta",
diff --git a/R/class_mrgmod.R b/R/class_mrgmod.R
index a63e421a..d45a6ea8 100644
--- a/R/class_mrgmod.R
+++ b/R/class_mrgmod.R
@@ -16,8 +16,8 @@
# along with mrgsolve. If not, see .
valid_funs <- function(x) {
- x1 <- length(x)==4
- x2 <- identical(names(x), c("main", "ode", "table", "config"))
+ x1 <- length(x)==5
+ x2 <- identical(names(x), c("main", "ode", "table", "event", "config"))
if(x1 & x2) return(list(TRUE,NULL))
msg <- c(
"Invalid functions specification.",
@@ -794,7 +794,8 @@ parin <- function(x) {
ss_n = 500,
ss_fixed = FALSE,
interrupt = -1,
- etasrc = "omega"
+ etasrc = "omega",
+ call_event = x@shlib$call_event
)
}
diff --git a/R/compile.R b/R/compile.R
index c08d0fa8..2fde0a9b 100644
--- a/R/compile.R
+++ b/R/compile.R
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 - 2023 Metrum Research Group
+# Copyright (C) 2013 - 2024 Metrum Research Group
#
# This file is part of mrgsolve.
#
@@ -17,12 +17,15 @@
generate_rdefs <- function(pars,
cmt,
- func,
- init_fun="",
- table_fun="",
- config_fun="",
- model="",omats,smats,
- set=list(),
+ func = "",
+ init_fun = "",
+ table_fun = "",
+ event_fun = "",
+ config_fun = "",
+ model = "",
+ omats,
+ smats,
+ set = list(),
plugin = NULL,
dbsyms = FALSE, ...) {
@@ -91,6 +94,7 @@ generate_rdefs <- function(pars,
c(paste0("#define __INITFUN___ ",init_fun),
paste0("#define __ODEFUN___ ",func),
paste0("#define __TABLECODE___ ", table_fun),
+ paste0("#define __EVENTFUN___ ", event_fun),
paste0("#define __CONFIGFUN___ ", config_fun),
paste0("#define __REGISTERFUN___ ", register_fun(model)),
paste0("#define _nEQ ", ncmt),
diff --git a/R/funset.R b/R/funset.R
index 79b5c8c3..59e31d14 100644
--- a/R/funset.R
+++ b/R/funset.R
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 - 2019 Metrum Research Group, LLC
+# Copyright (C) 2013 - 2024 Metrum Research Group
#
# This file is part of mrgsolve.
#
@@ -30,6 +30,7 @@ There was a problem accessing the model shared object.
main_func <- function(x) x@funs["main"]
ode_func <- function(x) x@funs["ode"]
table_func <- function(x) x@funs["table"]
+event_func <- function(x) x@funs["event"]
config_func <- function(x) x@funs["config"]
info_func <- function(x) x@funs["info"]
#nocov end
@@ -42,7 +43,7 @@ clean_symbol <- function(x) {
gsub("[[:punct:]]", "__", x)
}
-funs_create <- function(model, what = c("main", "ode", "table", "config")) {
+funs_create <- function(model, what = c("main", "ode", "table", "event", "config")) {
setNames(paste0("_model_", clean_symbol(model), "_", what ,"__"),what)
}
@@ -55,7 +56,7 @@ package_loaded <- function(x) {
}
funs <- function(x) {
- x@funs[c("main", "ode", "table", "config")]
+ x@funs[c("main", "ode", "table", "event", "config")]
}
model_loaded <- function(x) {
diff --git a/R/handle_spec_block.R b/R/handle_spec_block.R
index bfd09821..258a1402 100644
--- a/R/handle_spec_block.R
+++ b/R/handle_spec_block.R
@@ -566,6 +566,17 @@ handle_spec_block.specTABLE <- function(x, env, ...) {
return(x)
}
+#' @export
+handle_spec_block.specEVENT <- function(x, env, ...) {
+
+ x <- dump_opts(x)
+
+ pos <- attr(x,"pos")
+
+ check_block_data(x, env, pos)
+
+ return(x)
+}
# NMXML --------------------------------
#' @export
diff --git a/R/modlib.R b/R/modlib.R
index ed82ac5e..80025fbc 100644
--- a/R/modlib.R
+++ b/R/modlib.R
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 - 2021 Metrum Research Group
+# Copyright (C) 2013 - 2024 Metrum Research Group
#
# This file is part of mrgsolve.
#
@@ -55,8 +55,9 @@
##' mod <- mread("viral2", modlib())
##' mod <- mread("pred1", modlib())
##' mod <- mread("pbpk", modlib())
-##' mod <- mread("1005", modlib()) # embedded NONMEM result
+##' mod <- mread("1005", modlib()) # embedded NONMEM result
##' mod <- mread("nm-like", modlib()) # model with nonmem-like syntax
+##' mod <- mread("evtools", modlib())
##'
##' mrgsolve:::code(mod)
##' }
@@ -75,7 +76,7 @@ modlib <- function(model = NULL,...,list=FALSE) {
modlib_models <- c(
"pk1cmt", "pk2cmt", "pk3cmt", "pk", "pk1", "pk2", "popex",
"irm1", "irm2", "irm3", "pred1", "emax", "tmdd", "viral1",
- "viral2", "effect", "1005", "nm-like"
+ "viral2", "effect", "1005", "nm-like", "evtools"
)
#nocov end
diff --git a/R/modspec.R b/R/modspec.R
index fcdfb56d..2f8ce692 100644
--- a/R/modspec.R
+++ b/R/modspec.R
@@ -368,7 +368,7 @@ param_re_find <- "\\bparam\\s+\\w+\\s*="
# please-deprecate
move_global <- function(x,env) {
- what <- intersect(c("PREAMBLE","MAIN", "ODE", "TABLE", "PRED"),names(x))
+ what <- intersect(c("PREAMBLE","MAIN", "ODE", "TABLE", "EVENT", "PRED"),names(x))
if(length(what)==0) return(x)
@@ -495,12 +495,17 @@ move_global2 <- function(spec, env, build) {
if(!is.null(table$code)) {
spec$TABLE <- table$code
}
+ event <- c_vars(spec[["EVENT"]], context = "event")
+ if(!is.null(event$code)) {
+ spec$EVENT <- event$code
+ }
to_ns <- bind_rows(
pream$vars,
pred$vars,
main$vars,
ode$vars,
- table$vars
+ table$vars,
+ event$vars
)
vars <- bind_rows(glob$vars, to_ns)
if(any(cap <- to_ns$type=="capture")) {
@@ -536,7 +541,7 @@ move_global2 <- function(spec, env, build) {
}
find_cpp_dot <- function(spec, env) {
- to_check <- c("PREAMBLE", "MAIN", "PRED", "ODE", "TABLE", "GLOBAL")
+ to_check <- c("PREAMBLE", "MAIN", "PRED", "ODE", "EVENT", "TABLE", "GLOBAL")
x <- spec[names(spec) %in% to_check]
x <- unlist(x, use.names = FALSE)
# Narrow the search first; 10x speed up when searching for `pattern`
diff --git a/R/mread.R b/R/mread.R
index ac072ac4..e340fdbe 100644
--- a/R/mread.R
+++ b/R/mread.R
@@ -336,10 +336,11 @@ mread <- function(model, project = getOption("mrgsolve.project", getwd()),
rd <- generate_rdefs(
pars = Pars(x),
cmt = Cmt(x),
- ode_func(x),
- main_func(x),
- table_func(x),
- config_func(x),
+ func = ode_func(x),
+ init_fun = main_func(x),
+ table_fun = table_func(x),
+ event_fun = event_func(x),
+ config_fun = config_func(x),
model = model(x),
omats = omat(x),
smats = smat(x),
@@ -375,7 +376,7 @@ mread <- function(model, project = getOption("mrgsolve.project", getwd()),
}
# autodec
if("autodec" %in% names(plugin)) {
- auto_blocks <- c("PREAMBLE", "MAIN", "PRED", "ODE", "TABLE")
+ auto_blocks <- c("PREAMBLE", "MAIN", "PRED", "ODE", "TABLE", "EVENT")
auto_skip <- cvec_cs(ENV[["MRGSOLVE_AUTODEC_SKIP"]])
autov <- autodec_vars(spec, blocks = auto_blocks)
autov <- autodec_clean(
@@ -461,6 +462,7 @@ mread <- function(model, project = getOption("mrgsolve.project", getwd()),
x@shlib[["nm_import"]] <- mread.env[["nm_import"]]
x@shlib[["source"]] <- file.path(build[["soloc"]],build[["compfile"]])
x@shlib[["md5"]] <- build[["md5"]]
+ x@shlib[["call_event"]] <- "EVENT" %in% names(spec)
# build----
# In soloc directory
@@ -536,6 +538,10 @@ mread <- function(model, project = getOption("mrgsolve.project", getwd()),
dbs[["ode"]],
spec[["ODE"]],
"__END_ode__",
+ "\n// MODELED EVENTS:",
+ "__BEGIN_event__",
+ spec[["EVENT"]],
+ "__END_event__",
"\n// TABLE CODE BLOCK:",
"__BEGIN_table__",
dbs[["cmt"]],
diff --git a/R/nm-mode.R b/R/nm-mode.R
index 82884a19..f61d58a5 100644
--- a/R/nm-mode.R
+++ b/R/nm-mode.R
@@ -22,7 +22,7 @@ find_nm_vars <- function(spec) {
ans[["has_ode"]] <- "ODE" %in% names(spec)
FRDA <- c("F", "R", "D", "ALAG")
# CHeck non-ODE
- blocks_to_check <- c("PREAMBLE", "MAIN", "TABLE")
+ blocks_to_check <- c("PREAMBLE", "MAIN", "TABLE", "EVENT")
pmt <- unlist(spec[blocks_to_check], use.names = FALSE)
m1 <- find_nm_vars_impl(pmt)
# Check ODE
diff --git a/inst/base/modelheader.h b/inst/base/modelheader.h
index fc8694fe..5a781a8e 100644
--- a/inst/base/modelheader.h
+++ b/inst/base/modelheader.h
@@ -65,6 +65,8 @@ typedef double capture;
#define __END_main__ __DONE__
#define __BEGIN_table__ extern "C" { void __TABLECODE___(MRGSOLVE_TABLE_SIGNATURE) {
#define __END_table__ __DONE__
+#define __BEGIN_event__ extern "C" {void __EVENTFUN___(MRGSOLVE_EVENT_SIGNATURE) {
+#define __END_event__ __DONE__
#define __DONE__ }}
diff --git a/inst/base/mrgsolv.h b/inst/base/mrgsolv.h
index 58ab5219..2be79ada 100644
--- a/inst/base/mrgsolv.h
+++ b/inst/base/mrgsolv.h
@@ -132,6 +132,10 @@ typedef std::vector dvec;
#define MRGSOLVE_TABLE_SIGNATURE const dvec& _A_, const dvec& _A_0_, dvec& _THETA_, const dvec& _F_, const dvec& _R_, databox& self, const dvec& _pred_, dvec& _capture_, mrgsolve::resim& simeps
#define MRGSOLVE_TABLE_SIGNATURE_N 9
+//! signature for $EVENT
same as what we use for $TABLE
+#define MRGSOLVE_EVENT_SIGNATURE MRGSOLVE_TABLE_SIGNATURE
+#define MRGSOLVE_EVENT_SIGNATURE_N MRGSOLVE_TABLE_SIGNATURE_N
+
//! signature for $ODE
#define MRGSOLVE_ODE_SIGNATURE const double* _ODETIME_, const double* _A_, double* _DADT_, const dvec& _A_0_, const dvec& _THETA_, const bool _ss_flag_
#define MRGSOLVE_ODE_SIGNATURE_N 6
diff --git a/inst/include/odeproblem.h b/inst/include/odeproblem.h
index 76b51f0e..7e7a536e 100644
--- a/inst/include/odeproblem.h
+++ b/inst/include/odeproblem.h
@@ -48,6 +48,9 @@ typedef void (*init_func)(MRGSOLVE_INIT_SIGNATURE);
//! $TABLE
function
typedef void (*table_func)(MRGSOLVE_TABLE_SIGNATURE);
+//! $EVENT
function
+typedef void (*event_func)(MRGSOLVE_EVENT_SIGNATURE);
+
//! $ODE
function
typedef void (*deriv_func)(MRGSOLVE_ODE_SIGNATURE);
@@ -115,6 +118,7 @@ class odeproblem {
void table_call();
void table_init_call();
+ void event_call();
void config_call();
void set_d(rec_ptr this_rec);
@@ -249,6 +253,7 @@ class odeproblem {
deriv_func Derivs; ///< $ODE
function
init_func Inits; ///< $MAIN
function
table_func Table; ///< $TABLE
function
+ event_func Event; ///< $EVENT
function
config_func Config; ///< $PREAMBLE
function
bool Do_Init_Calc; ///< Flag regulating whether or not initials are taken from $MAIN
diff --git a/inst/maintenance/unit-cpp/test-event-block.R b/inst/maintenance/unit-cpp/test-event-block.R
new file mode 100644
index 00000000..46c58045
--- /dev/null
+++ b/inst/maintenance/unit-cpp/test-event-block.R
@@ -0,0 +1,129 @@
+library(testthat)
+library(mrgsolve)
+library(dplyr)
+
+Sys.setenv(R_TESTS="")
+
+options("mrgsolve_mread_quiet"=TRUE)
+
+local_edition(3)
+
+code_event <- '
+$PLUGIN evtools nm-vars autodec
+
+$PARAM
+Ii = 24
+Ss = 1
+Addl = 3
+Amt = 100
+Rate = 20
+CL = 2
+V = 20
+
+$PKMODEL cmt = "B"
+
+$EVENT
+if(TIME==0) {
+ evt::ev dose = evt::infuse(Amt, 1, Rate);
+ evt::ss(dose, Ss);
+ evt::ii(dose, Ii);
+ evt::addl(dose, Addl);
+ self.push(dose);
+}
+capture b = A(1)/V;
+capture c = 1.23;
+double d = 50;
+
+$ERROR
+capture cp = B/V;
+e = d/2;
+
+$CAPTURE e d
+'
+
+code_error <- '
+$PLUGIN evtools nm-vars autodec
+
+$PARAM
+Ii = 24
+Ss = 1
+Addl = 3
+Amt = 100
+Rate = 20
+CL = 2
+V = 20
+
+$PKMODEL cmt = "B"
+
+$ERROR
+if(TIME==0) {
+ evt::ev dose = evt::infuse(Amt, 1, Rate);
+ evt::ss(dose, Ss);
+ evt::ii(dose, Ii);
+ evt::addl(dose, Addl);
+ self.push(dose);
+}
+capture cp = B/V;
+'
+
+mod1 <- mcode("test-event", code_event, delta = 0.1, end = 120)
+mod2 <- mcode("test-error", code_error, delta = 0.1, end = 120)
+
+outev <- mrgsim(mod1)
+outer <- mrgsim(mod2)
+
+test_that("$EVENT result matches $TABLE results", {
+ expect_identical(outev$B, outer$B)
+ # Known that cp isn't calculated when $TABLE is used
+ expect_equal(outer$cp[1], 0)
+ # Using $EVENT allows this to be calculated
+ expect_equal(outev$cp[1], outev$B[1]/mod1$V)
+ i <- seq(nrow(outer))[-1]
+ expect_equal(outer$cp[i], outev$cp[i])
+})
+
+test_that("declare inside $EVENT", {
+ expect_true(all(outev$d == 50))
+ expect_true(all(outev$e == outev$d/2))
+})
+
+test_that("capture from $EVENT", {
+ expect_true(all(abs(outev$c - 1.23) < 1e-7))
+ expect_equal(outev$b, outer$cp)
+})
+
+test_that("check internals", {
+ f <- mrgsolve:::funset(mod1)
+ expect_equal(nrow(f$symbols), 5)
+ expect_true(all(f$symbols$loaded))
+ expect_equal(f$symbols$name[4], "_model_test__event_event__")
+
+ p <- mrgsolve:::pointers(mod1)
+ expect_equal(length(p), 5)
+ expect_equal(names(p)[4], "event")
+
+ expect_true(mod1@shlib$call_event)
+ expect_false(mod2@shlib$call_event)
+
+ df <- as.list(mod1)$cpp_variables
+ cap <- df[df$type=="capture",]
+ expect_equal(cap$var, c("cp", "b", "c"))
+ expect_equal(cap$context, c("table", "event", "event"))
+
+ auto <- df[df$context=="auto", ]
+ expect_true(all(auto$type=="double"))
+ expect_equal(auto$var[1], "e")
+
+ f <- mrgsolve:::funset(house())
+ expect_equal(nrow(f$symbols), 5)
+ expect_true(all(f$symbols$loaded))
+ expect_equal(f$symbols$name[4], "_model_housemodel_event__")
+
+ p <- mrgsolve:::pointers(house())
+ expect_equal(length(p), 5)
+ expect_equal(names(p)[4], "event")
+
+ expect_false(house()@shlib$call_event)
+})
+
+
diff --git a/inst/maintenance/unit/test-modlib.R b/inst/maintenance/unit/test-modlib.R
index dea3860d..7ba71684 100644
--- a/inst/maintenance/unit/test-modlib.R
+++ b/inst/maintenance/unit/test-modlib.R
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 - 2020 Metrum Research Group
+# Copyright (C) 2013 - 2024 Metrum Research Group
#
# This file is part of mrgsolve.
#
@@ -100,9 +100,21 @@ test_that("all modlib models", {
expect_is(x[[1]],"mrgmod")
expect_is(x[[2]],"mrgsims")
+ x <- test_lib("pbpk")
+ expect_is(x[[1]],"mrgmod")
+ expect_is(x[[2]],"mrgsims")
+
+ x <- test_lib("1005")
+ expect_is(x[[1]],"mrgmod")
+ expect_is(x[[2]],"mrgsims")
+
x <- test_lib("nm-like")
expect_is(x[[1]],"mrgmod")
expect_is(x[[2]],"mrgsims")
+
+ x <- test_lib("evtools")
+ expect_is(x[[1]],"mrgmod")
+ expect_is(x[[2]],"mrgsims")
})
diff --git a/inst/models/evtools.cpp b/inst/models/evtools.cpp
new file mode 100644
index 00000000..a11329b1
--- /dev/null
+++ b/inst/models/evtools.cpp
@@ -0,0 +1,68 @@
+$PROB
+# Example model using evtools plugin
+
+- Regimen 1 is a single infusion dose to DEPOT
+- Regimen 2 is steady state bolus dosing
+- Regimen 3 is a dosing regimen using `regimen` object
+
+$PLUGIN evtools
+
+$GLOBAL
+evt::regimen reg;
+
+$SET end = 264, delta = 0.5
+
+$PARAM
+TVKA = 1.2, TVCL = 1, TVV = 20
+Amt = 100, Dur = 0, Ii = 24, Addl = 9, Ss = 1
+REG = 1, Until = 24*8
+
+$INPUT WT = 70
+
+$PKMODEL cmt = "DEPOT CENT", depot = TRUE
+
+$PREAMBLE
+reg.init(self);
+
+$PK
+if(NEWIND < 1) reg.init(self);
+
+double CL = exp(log(TVCL) + 0.75*log(WT/70) + ETA(1));
+double V = exp(log(TVV) + log(WT/70) + ETA(2));
+double KA = exp(log(TVKA) + ETA(3));
+
+double Rate = Dur > 0 ? Amt / Dur : 0;
+
+$OMEGA 0.09 0.1 0.01
+
+$SIGMA 0
+
+$EVENT
+if(TIME != 0) return;
+
+if(REG==1) {
+ evt::infuse(self, Amt, 2, Rate);
+}
+
+if(REG==2) {
+ evt::ev dose = evt::bolus(Amt, 1);
+ evt::ii(dose, Ii);
+ evt::addl(dose, Addl);
+ evt::ss(dose, Ss);
+ self.push(dose);
+}
+
+if(REG==3) {
+ reg.init(self);
+ reg.amt(Amt);
+ reg.cmt(1);
+ reg.rate(Rate);
+ reg.ii(Ii);
+ reg.until(Until);
+}
+
+$TABLE
+capture IPRED = CENT/V;
+capture DV = IPRED*exp(EPS(1));
+
+if(REG==3) reg.execute();
diff --git a/man/modlib.Rd b/man/modlib.Rd
index 5f116758..0768018f 100644
--- a/man/modlib.Rd
+++ b/man/modlib.Rd
@@ -47,8 +47,9 @@ mod <- mread("viral1", modlib())
mod <- mread("viral2", modlib())
mod <- mread("pred1", modlib())
mod <- mread("pbpk", modlib())
-mod <- mread("1005", modlib()) # embedded NONMEM result
+mod <- mread("1005", modlib()) # embedded NONMEM result
mod <- mread("nm-like", modlib()) # model with nonmem-like syntax
+mod <- mread("evtools", modlib())
mrgsolve:::code(mod)
}
diff --git a/src/devtran.cpp b/src/devtran.cpp
index bac83507..e8dd3f82 100644
--- a/src/devtran.cpp
+++ b/src/devtran.cpp
@@ -61,6 +61,7 @@ Rcpp::List DEVTRAN(const Rcpp::List parin,
const bool tad = Rcpp::as (parin["tad"]);
const bool nocb = Rcpp::as (parin["nocb"]);
bool obsaug = Rcpp::as (parin["obsaug"] );
+ bool call_event = Rcpp::as (parin["call_event"]);
obsaug = obsaug & (data.nrow() > 0);
// Grab items from the model object --------------------
@@ -616,9 +617,12 @@ Rcpp::List DEVTRAN(const Rcpp::List parin,
}
if(!this_rec->is_lagged()) {
- prob.table_call();
+ if(call_event) {
+ prob.event_call();
+ } else {
+ prob.table_call();
+ }
}
-
if(prob.any_mtime()) {
// Will set used_mtimehx only if we push back
std::vector mt = prob.mtimes();
@@ -716,7 +720,11 @@ Rcpp::List DEVTRAN(const Rcpp::List parin,
used_mtimehx = mtimehx.size() > 0;
prob.clear_mtime();
} // Close handling of modeled events
-
+
+ if(call_event && !this_rec->is_lagged()) {
+ prob.table_call();
+ }
+
if(this_rec->output()) {
ans(crow,0) = id;
ans(crow,1) = tto;
diff --git a/src/housemodel-mread-header.h b/src/housemodel-mread-header.h
index 5845b2ec..672c9812 100644
--- a/src/housemodel-mread-header.h
+++ b/src/housemodel-mread-header.h
@@ -41,6 +41,7 @@ typedef double localdouble;
#define __INITFUN___ _model_housemodel_main__
#define __ODEFUN___ _model_housemodel_ode__
#define __TABLECODE___ _model_housemodel_table__
+#define __EVENTFUN___ _model_housemodel_event__
#define __CONFIGFUN___ _model_housemodel_config__
#define __REGISTERFUN___ R_init_housemodel
#define _nEQ 3
diff --git a/src/housemodel-mread-source.cpp b/src/housemodel-mread-source.cpp
index f7e5a130..21030372 100644
--- a/src/housemodel-mread-source.cpp
+++ b/src/housemodel-mread-source.cpp
@@ -24,6 +24,10 @@ dxdt_CENT = KAi*GUT - (CLi/VCi)*CENT;
dxdt_RESP = KIN*(1-INH) - KOUTi*RESP;
__END_ode__
+// MODELED EVENTS:
+__BEGIN_event__
+__END_event__
+
// TABLE CODE BLOCK:
__BEGIN_table__
DV = CP*exp(EXPO);
diff --git a/src/mrgsolve.cpp b/src/mrgsolve.cpp
index 382c5e9a..4f43a2a5 100644
--- a/src/mrgsolve.cpp
+++ b/src/mrgsolve.cpp
@@ -453,5 +453,3 @@ Rcpp::List mat2df(Rcpp::NumericMatrix const& x) {
}
#endif
-
-
diff --git a/src/mrgsolve_init.cpp b/src/mrgsolve_init.cpp
index 67249280..88caa09a 100644
--- a/src/mrgsolve_init.cpp
+++ b/src/mrgsolve_init.cpp
@@ -61,6 +61,7 @@ RcppExport void _model_housemodel_main__(MRGSOLVE_INIT_SIGNATURE);
RcppExport void _model_housemodel_ode__(MRGSOLVE_ODE_SIGNATURE);
RcppExport void _model_housemodel_table__(MRGSOLVE_TABLE_SIGNATURE);
RcppExport void _model_housemodel_config__(MRGSOLVE_CONFIG_SIGNATURE);
+RcppExport void _model_housemodel_event__(MRGSOLVE_EVENT_SIGNATURE);
static R_CallMethodDef callEntryPoints[] = {
CALLDEF(_mrgsolve_get_tokens,1),
@@ -75,6 +76,7 @@ static R_CallMethodDef callEntryPoints[] = {
CALLDEF(_model_housemodel_main__,MRGSOLVE_INIT_SIGNATURE_N),
CALLDEF(_model_housemodel_ode__,MRGSOLVE_ODE_SIGNATURE_N),
CALLDEF(_model_housemodel_table__,MRGSOLVE_TABLE_SIGNATURE_N),
+ CALLDEF(_model_housemodel_event__,MRGSOLVE_EVENT_SIGNATURE_N),
CALLDEF(_model_housemodel_config__,MRGSOLVE_CONFIG_SIGNATURE_N),
{NULL, NULL, 0}
};
diff --git a/src/odeproblem.cpp b/src/odeproblem.cpp
index a50a6bc1..5a3047a3 100644
--- a/src/odeproblem.cpp
+++ b/src/odeproblem.cpp
@@ -113,9 +113,10 @@ odeproblem::odeproblem(Rcpp::List param,
*reinterpret_cast(&Inits) = R_ExternalPtrAddr(funs["main"]);
*reinterpret_cast(&Table) = R_ExternalPtrAddr(funs["table"]);
+ *reinterpret_cast(&Event) = R_ExternalPtrAddr(funs["event"]);
*reinterpret_cast(&Derivs) = R_ExternalPtrAddr(funs["ode"]);
*reinterpret_cast(&Config) = R_ExternalPtrAddr(funs["config"]);
-
+
Capture.assign(n_capture_,0.0);
simeta = mrgsolve::resim(&dosimeta,reinterpret_cast(this));
@@ -244,6 +245,11 @@ void odeproblem::table_call() {
Table(Y,Init_value,Param,F,R,d,pred,Capture,simeps);
}
+//! Call $EVENT
function.
+void odeproblem::event_call() {
+ Event(Y,Init_value,Param,F,R,d,pred,Capture,simeps);
+}
+
//! Call $PREAMBLE
function.
void odeproblem::config_call() {
Config(d,Param,Neq,Npar);
@@ -684,6 +690,7 @@ void odeproblem::copy_parin(const Rcpp::List& parin, const Rcpp::S4& mod) {
void odeproblem::copy_funs(const Rcpp::List& funs) {
*reinterpret_cast(&Inits) = R_ExternalPtrAddr(funs["main"]);
*reinterpret_cast(&Table) = R_ExternalPtrAddr(funs["table"]);
+ *reinterpret_cast(&Event) = R_ExternalPtrAddr(funs["event"]);
*reinterpret_cast(&Derivs) = R_ExternalPtrAddr(funs["ode"]);
*reinterpret_cast(&Config) = R_ExternalPtrAddr(funs["config"]);
}