Nope… brms is just fine. You just need to get used as to how the brms stan source generation works. The make_stancode thing is the way to go… although I don’t use the parse option as it is easier first to dump that into a file and check it out. Here is what samples for me just fine:
fo_model2 <- "
vector fo2(real t, //time
vector y, // the state
real k1){ // the parameter next to A0
vector[1] dydt; // dimension of ODE
dydt[1] = - k1 * y[1]; // ODE
return dydt; // returns a 1-dimensional vector
}
// function called from brms: integration of ODEs
vector fo_ode2(data vector time, vector vA0, vector vk1) {
vector[1] y0 = rep_vector(vA0[1], 1); //one initial value
int N = size(time);
vector[1] y_hat_ode[N] = ode_rk45(fo2, y0 ,0.0,to_array_1d(time),vk1[1]);
vector[N] y_hat;
for(i in 1:N) y_hat[i] = y_hat_ode[i,1];
return(y_hat);
}
"
df_sim_ode <- df_sim[-1,] #remove the first datapoint at t0
fo_formula <- bf(y_obs~fo_ode2(time,A0,k1),
A0~1,
k1~1,
nl=TRUE, loop=FALSE)
fo_priors <- c(prior(normal(100,10),nlpar=A0),
prior(normal(0.2,0.1), nlpar=k1),
prior(cauchy(0,10), class=sigma)
)
fo_result2 <- brm(data=df_sim_ode,family = gaussian,formula=fo_formula,prior=fo_priors, inits=0,iter=4000,chains=4, cores=4, stanvars = stanvar(scode=fo_model2, block="functions"), backend="cmdstanr", file="fo_result2")