Guidelines for Stan models with ODE-based dynamics using modern interfaces
Guides Stan modeling for ODE-based dynamics using modern solver interfaces and best practices.
/plugin marketplace add sunxd3/bayesian-statistician-plugin/plugin install sunxd3-bayesian-statistician@sunxd3/bayesian-statistician-pluginThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Use this skill when writing Stan models where latent dynamics are defined by ODEs: epidemic models (SIR/SEIR), PK/PD compartment models, population dynamics, biochemical reactions, growth models.
Uses Stan 2.24+ modern ODE interface (ode_rk45, ode_bdf, ode_adams, adjoint solvers), not legacy integrate_ode_*.
Function signature:
functions {
vector ode_rhs(real t, vector y, array[] real theta, array[] real x_r, array[] int x_i) {
vector[N] dydt;
// fill dydt based on y and theta
return dydt;
}
}
Solver calls:
ode_rk45(ode_rhs, y0, t0, ts, theta, x_r, x_i) - non-stiff (default)ode_bdf(ode_rhs, y0, t0, ts, theta, x_r, x_i) - stiff systemsode_adams(ode_rhs, y0, t0, ts, theta, x_r, x_i) - smooth, long horizonsode_adjoint_* - many parameters relative to state dimensionAdd _tol suffix for configurable tolerances: ode_rk45_tol(..., rel_tol, abs_tol, max_num_steps, ...)
Returns: array[T] vector[N] where T = length(ts), N = state dimension
Transformed parameters (when ODE enters likelihood):
transformed parameters {
array[T] vector[N] x_hat;
array[] real theta = {beta, gamma}; // pack parameters
x_hat = ode_rk45(ode_rhs, y0, t0, ts, theta, {}, {});
}
Generated quantities (predictions, forecasts): Include y_rep and log_lik following stan-coding skill guidelines.
functions {
vector sir_rhs(real t, vector y, array[] real theta, array[] real x_r, array[] int x_i) {
vector[3] dydt;
real beta = theta[1];
real gamma = theta[2];
real N_pop = x_r[1];
dydt[1] = -beta * y[1] * y[2] / N_pop; // dS/dt
dydt[2] = beta * y[1] * y[2] / N_pop - gamma * y[2]; // dI/dt
dydt[3] = gamma * y[2]; // dR/dt
return dydt;
}
}
transformed parameters {
array[T] vector[3] x_hat;
x_hat = ode_rk45(sir_rhs, y0, t0, ts, {beta, gamma}, {N_pop}, {});
}
model {
beta ~ lognormal(0, 1);
gamma ~ lognormal(0, 1);
for (t in 1:T) {
I_obs[t] ~ poisson(x_hat[t, 2]); // observe infected count
}
}
For multiple subjects with subject-specific ODE parameters:
r[n] = exp(mu_log_r + sigma_log_r * z_r[n])Default: ode_rk45 with rel_tol ≈ 1e-6, abs_tol ≈ (typical state scale) × 1e-6, max_num_steps ≈ 1e4-1e5
Switch to ode_bdf if:
Use ode_adams if: Smooth, non-stiff systems over long time horizons
Use ode_adjoint_* if: Many parameters relative to state dimension (hierarchical models with per-subject parameters)
Tolerances: ODE error should be much smaller than observation noise. Rarely need rel_tol < 1e-8. Can relax slightly (1e-6 → 1e-5) if HMC is slow but stable.
Max steps exceeded:
ode_bdf if stiffmax_num_steps as last resortDivergences:
Performance:
reduce_sum parallelization for multi-subject modelsFor ODE model examples and patterns, search:
Use WebSearch or WebFetch to find domain-specific ODE modeling examples.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.