traitecoevo / plant

Trait-Driven Models of Ecology and Evolution :evergreen_tree:
https://traitecoevo.github.io/plant
53 stars 20 forks source link

[simplify interface] Clarify how to control step sizes in ode stepper #411

Closed dfalster closed 1 month ago

dfalster commented 1 month ago

It's currently unclear how to

dfalster commented 1 month ago
#library(plant)
devtools::load_all()

plant_log_console()
params <- scm_base_parameters("FF16")
params$max_patch_lifetime <- 10

# configure a patch containing a single species:
p0 <- expand_parameters(trait_matrix(0.0825, "lma"), params)
p1 <- build_schedule(p0)
out0 <- run_scm(p0)
out0 <- run_scm_collect(p0)

p0$ode_times <- rep(0.1, 100

all.equal(p1, p0)
all.equal(p1$node_schedule_times, p0$node_schedule_times)

p1b <- p1
p1b$ode_times <- p1$ode_times[-c(205:210)]

out0 <- run_scm(p0)
out1 <- run_scm(p1)
out2 <- run_scm(p1, use_ode_times = TRUE)
out2b <- run_scm(p1b, use_ode_times = TRUE)

length(p1$ode_times)
length(p1b$ode_times)

length(out0$ode_times)
length(out1$ode_times)
length(out2$ode_times)
length(out2b$ode_times)

p1

names(result)
length(result$ode_times)

result$ode_times |>
  diff() %>%
  range()

Can we limit step sizes at upper end? Yes!

params$max_patch_lifetime <- 10
p0 <- expand_parameters(trait_matrix(0.0825, "lma"), params)

ctrl <- scm_base_control()
ctrl$ode_step_size_max <- 0.1

result2 <- run_scm(p0, ctrl = ctrl)

length(result2$ode_times)

result2$ode_times |>
  diff() %>%
  hist()

Can we limit step sizes at lower end?

ctrl <- scm_base_control()
ctrl$ode_step_size_min <- 0.01
ctrl$ode_step_size_initial <- 0.01

p0b <- p0
p0b$node_schedule_times[[1]] <- c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0)
result2 <- run_scm(p0b, ctrl = ctrl)

result2$ode_times

Can we fix step sizes?

Option 1

yes, by specifying ode_times in parameters

ctrl <- scm_base_control()

p0c <- p0
p0c$node_schedule_times[[1]] <- c(0, 0.11, 0.41, 0.81, 1.21)
p0c$ode_times <- seq(0, p0$max_patch_lifetime, by=0.02)

result2 <- run_scm(p0c, ctrl = ctrl, use_ode_times = TRUE)

result2$ode_times

Option 2

yes, by specifying max and min step sizes. But this could result in odd times, dpeending on the cohort schedule

ctrl <- scm_base_control()
ctrl$ode_step_size_min <- 0.1
ctrl$ode_step_size_max <- 0.1
ctrl$ode_step_size_initial <- 0.1

p0c <- p0
p0c$node_schedule_times[[1]] <- c(0, 0.11, 0.44, 0.88, 1.212)

result2 <- run_scm(p0c, ctrl = ctrl)

result2$ode_times

How do we want to contol ode_times?

current can provide with pars, but this is a bit clunky. could have option to pass in ode_times, use if supplied?

Better document

Need easy demo showing how to make desired changes

Need a graphic of document saying how all the parts/classes of the odesolver relate to each other

ode controls