mrc-ide / odin

ᚩ A DSL for describing and solving differential equations in R
https://mrc-ide.github.io/odin
Other
102 stars 12 forks source link

Bug parsing with intermediate variables #289

Open CGMossa opened 1 year ago

CGMossa commented 1 year ago

While working on this example, I experienced this error:


Unused equation: foi_mat
    foi_mat <- user() # (line 8)
Generating model in c
ℹ Re-compiling odineec1549a (debug build)
── R CMD INSTALL ───────────────────────────────────────────────────────────────────────────────────────
─  installing *source* package 'odineec1549a' ...
   ** using staged installation
   ** libs
   using C compiler: 'gcc.exe (GCC) 12.2.0'
   gcc  -I"C:/Users/minin/scoop/apps/r/current/include" -DNDEBUG     -I"c:/rtools43/x86_64-w64-mingw32.static.posix/include"     -O2 -Wall -gdwarf-2 -mfpmath=sse -msse2 -mstackrealign  -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c odin.c -o odin.o
   odin.c:n function 'odin_rhs
   odin.c:204:63:error: ieclared (first use in this function)
     204 |   double delta_transmission = internal->transmission_rate * S[i * I[i - 1];
         |                                                               ^
   odin.c:204:63:note: each undeclared identifier is reported only once for each function it appears in
   make: *** [C:/Users/minin/scoop/apps/r/current/etc/x64/Makeconf:265: odin.o] Error 1
   ERROR: compilation failed for package 'odineec1549a'
─  removing 'C:/Users/minin/AppData/Local/Temp/RtmpQJ1XDn/devtools_install_19e06cbf1fb0/odineec1549a'
Error in `(function (command = NULL, args = character(), error_on_status = TRUE, …`:
! System command 'Rcmd.exe' failed
---
Exit status: 1
stdout & stderr: <printed>
---
Type .Last.error to see the more details.
> .Last.error

This occurs when running this:


odin::odin({
  delta_transmission <- transmission_rate * S[i] * I[i]
  deriv(S[]) <- delta_transmission
  deriv(I[]) <- +transmission_rate * S[i] * I[i] - recovery_rate * I[i]

  transmission_rate <- user(0.005)
  recovery_rate <- user(0.01)
  S0[] <- user()
  I0[] <- user()
  foi_mat <- user()
  initial(S[]) <- S0[i]
  initial(I[]) <- I0[i]
  dim(S0) <- user()
  dim(S) <- N
  dim(I) <- N
  dim(I0) <- N
  N <- length(S0)
},
verbose = TRUE,
# verbose = TRUE, validate = TRUE, target = "c", pretty = TRUE,
skip_cache = FALSE) ->
  model_generator

Backtrace:

Details

```r Backtrace: 1. odin::odin({ … 2. odin::odin_(xx, verbose, target, workdir, validate, pretty, skip_cache, … 3. odin:::odin_generate(ir, options) 4. odin:::odin_c_wrapper(ir, options) 5. odin:::compile_dll(dest, compile_attributes = FALSE, quiet = quiet) 6. withr::with_envvar(c(R_MAKEVARS_USER = makevars), pkgbuild::compile_dll(...)) 7. base::force(code) 8. pkgbuild::compile_dll(...) 9. pkgbuild:::install_min(path, dest = install_dir, components = "libs", args = if (needs_clean(path)) "--precle… 10. pkgbuild::rcmd_build_tools("INSTALL", c(path, paste("--library=", dest, … 11. pkgbuild::with_build_tools({ … 12. withr::with_path(rtools_path(), code) 13. base::force(code) 14. base::withCallingHandlers(callr::rcmd_safe(..., env = env, spinner = FALSE, … 15. callr::rcmd_safe(..., env = env, spinner = FALSE, show = FALSE, … 16. callr:::run_r(options) 17. base::with(options, with_envvar(env, do.call(processx::run, c(list(bin, … 18. base::with.default(options, with_envvar(env, do.call(processx::run, … 19. base::eval(substitute(expr), data, enclos = parent.frame()) 20. base::eval(substitute(expr), data, enclos = parent.frame()) 21. callr:::with_envvar(env, do.call(processx::run, c(list(bin, args = real_cmdargs, … 22. base::force(code) 23. base::do.call(processx::run, c(list(bin, args = real_cmdargs, stdout_line_callback = real_callback(stdou… 24. (function (command = NULL, args = character(), error_on_status = TRUE, … 25. base::throw(new_process_error(res, call = sys.call(), echo = echo, … 26. | base::signalCondition(cond) 27. (function (e) … 28. asNamespace("callr")$err$throw(e) ```

CGMossa commented 1 year ago

Another example of this, is an intermediate variable that is supposed to be a vector (array)

  source_id <- user()
  target_id <- user()
  Total[] <- S[i] + I[i]
  output(source_prevalence) <- I[as.integer(source_id)] / Total[as.integer(source_id)]
  output(target_prevalence) <- I[as.integer(target_id)] / Total[as.integer(target_id)]

This works, but if I remove the as.integer, wild errors arise.

The logic here is I have many S and I compartments, and I only want to pickout the designated "source" and "target" cells, and their compartments. So I pass scalar integers to the system and use that to index the arrays.

Full error message:

   using C compiler: 'gcc.exe (GCC) 12.2.0'
   gcc  -I"C:/Users/minin/scoop/apps/r/current/include" -DNDEBUG     -I"c:/rtools43/x86_64-w64-mingw32.static.posix/include"     -O2 -Wall -gdwarf-2 -mfpmath=sse -msse2 -mstackrealign  -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c odin.c -o odin.o
   odin.c:n function 'odin_rhs
   odin.c:293:18:error:  subscript is not an integer
     293 |     output[0] = I[nal->source_id - 1] / (double) internal->Total[internal->source_id - 1];
         |                  ^
   odin.c:293:70:error:  subscript is not an integer
     293 |     output[0] = I[internal->source_id - 1] / (double) internal->Total[nal->source_id - 1];
         |                                                                      ^
   odin.c:294:18:error:  subscript is not an integer
     294 |     output[1] = I[nal->target_id - 1] / (double) internal->Total[internal->target_id - 1];
         |                  ^
   odin.c:294:70:error:  subscript is not an integer
     294 |     output[1] = I[internal->target_id - 1] / (double) internal->Total[nal->target_id - 1];
         |                                                                      ^
   odin.c:n function 'odin_output_dde
   odin.c:310:16:error:  subscript is not an integer
     310 |   output[0] = I[nal->source_id - 1] / (double) internal->Total[internal->source_id - 1];
         |                ^
   odin.c:310:68:error:  subscript is not an integer
     310 |   output[0] = I[internal->source_id - 1] / (double) internal->Total[nal->source_id - 1];
         |                                                                    ^
   odin.c:311:16:error:  subscript is not an integer
     311 |   output[1] = I[nal->target_id - 1] / (double) internal->Total[internal->target_id - 1];
         |                ^
   odin.c:311:68:error:  subscript is not an integer
     311 |   output[1] = I[internal->target_id - 1] / (double) internal->Total[nal->target_id - 1];
         |                                                                    ^
   make: *** [C:/Users/minin/scoop/apps/r/current/etc/x64/Makeconf:265: odin.o] Error 1
   ERROR: compilation failed for package 'odin4378698c'
─  removing 'C:/Users/minin/AppData/Local/Temp/RtmpcbvBoR/devtools_install_5ebc7bd31f31/odin4378698c'
Error in `(function (command = NULL, args = character(), error_on_status = TRUE, …`:
! System command 'Rcmd.exe' failed
---
Exit status: 1
stdout & stderr: <printed>
---

(this is when Total has as.integer but not I):

Generating model in c
ℹ Re-compiling odin19bcfc16 (debug build)
── R CMD INSTALL ────────────────────────────────────────────────────────────────────────────────────────
─  installing *source* package 'odin19bcfc16' ...
   ** using staged installation
   ** libs
   using C compiler: 'gcc.exe (GCC) 12.2.0'
   gcc  -I"C:/Users/minin/scoop/apps/r/current/include" -DNDEBUG     -I"c:/rtools43/x86_64-w64-mingw32.static.posix/include"     -O2 -Wall -gdwarf-2 -mfpmath=sse -msse2 -mstackrealign  -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c odin.c -o odin.o
   odin.c:n function 'odin_rhs
   odin.c:293:18:error:  subscript is not an integer
     293 |     output[0] = I[nal->source_id - 1] / (double) internal->Total[(int) (internal->source_id) - 1];
         |                  ^
   odin.c:294:18:error:  subscript is not an integer
     294 |     output[1] = I[nal->target_id - 1] / (double) internal->Total[(int) (internal->target_id) - 1];
         |                  ^
   odin.c:n function 'odin_output_dde
   odin.c:310:16:error:  subscript is not an integer
     310 |   output[0] = I[nal->source_id - 1] / (double) internal->Total[(int) (internal->source_id) - 1];
         |                ^
   odin.c:311:16:error:  subscript is not an integer
     311 |   output[1] = I[nal->target_id - 1] / (double) internal->Total[(int) (internal->target_id) - 1];
         |                ^
   make: *** [C:/Users/minin/scoop/apps/r/current/etc/x64/Makeconf:265: odin.o] Error 1
   ERROR: compilation failed for package 'odin19bcfc16'
─  removing 'C:/Users/minin/AppData/Local/Temp/RtmpcbvBoR/devtools_install_5ebc7d3c48f5/odin19bcfc16'
Error in `(function (command = NULL, args = character(), error_on_status = TRUE, …`:
! System command 'Rcmd.exe' failed
richfitz commented 1 year ago

A minimal version of this bug:

odin::odin({
  a <- x[i]
  dim(x) <- 5
  x[] <- 0
  deriv(y) <- a
  initial(y) <- 0
})

This should be an error before it generates C code (and I am surprised we don't catch this already) as you cannot use i where the lhs is not an array assignment.

In your specific case you should write:

  delta_transmission[i] <- transmission_rate * S[i] * I[i]
  dim(delta_transmission) <- N
CGMossa commented 1 year ago

That totally makes sense. Do you want me to close this? Or should I update the name?

richfitz commented 1 year ago

Please leave it open, it's a bug and the example is good