Getting two errors "Rejecting initial value" and "1000 transitions using 10 leapfrog steps per transition would take" while running stan

I’ve got the following reported daily cases of covid-19 for the UK,

library(deSolve)
library(dplyr)
library(ggplot2)
library(rstan)
rstan_options(auto_write = TRUE)
options(mc.cores = parallel::detectCores())
cases <- c(0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 5, 0, 1, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 5, 3, 13, 4, 11, 34, 30, 48,
43, 67, 48, 61, 74, 0, 342, 342, 0, 403, 407, 676, 63, 1294, 1035,
665, 967, 1427, 1452, 2129, 2885, 2546, 2433, 2619, 3009, 4324, 4244,
4450, 3735, 5903, 3802, 3634, 5491, 4344, 8681, 5233, 5288, 4342,
5252, 4603, 4617, 5599, 5525, 5850, 4676, 4301, 4451, 4583, 5386,
4913, 4463, 4309, 3996, 4076, 6032, 6201, 4806, 4339, 3985, 4406,
6111, 5614, 4649, 3896, 3923)
N = length(cases)
sample_time = 1:N

Note that I added the libraries I am using and other definitions for clarity. I have a system of ODEs similar to SEIR model and I want to estimate the parameters of it based on the data I have in hand (i.e number of cases). I made my stan function as follow:

# The Stan model statement:
cat(
'
functions {
  
  real[] SI(real t,
            real[] y,
            real[] params,
            real[] x_r,
            int[] x_i) {
      
      real dydt[8];
      
      dydt[1] = - params[2] * params[1] * y[1] * y[6] - params[1] * y[1] * y[5] - params[1] * y[8] * y[1] - params[3] * y[7] * y[1];
      dydt[2] = params[2] * params[1] * y[1] * y[6] + (1 - params[4]) * params[1] * y[1] * y[5] + (1 - params[4]) * params[1] * y[8] * y[1] + (1 - params[4]) * params[3] * y[7] * y[1] - y[2] / params[5];
      dydt[3] = params[6] * params[4] * params[1] * y[1] * y[5] + params[7] * params[4] * params[1] * y[8] * y[1] + params[8] * params[4] * params[3] * y[7] * y[1] - y[3] / params[5];
      dydt[4] = (1 - params[6]) * params[4] * params[1] * y[1] * y[5] + (1 - params[7]) * params[4] * params[1] * y[8] * y[1] + (1 - params[8]) * params[4] * params[3] * y[7] * y[1] - y[4] / params[5];
      dydt[5] = params[9] * y[2] / params[5] - y[5] / params[10];
      dydt[6] = (1 - params[9]) * y[2] / params[5] - y[6] / params[11];
      dydt[7] = y[3] / params[5] - y[7] / params[12];
      dydt[8] = y[4] / params[5] - y[8] / params[13];
      
      return dydt;
    }
  
}

data {
  int<lower = 1> n_obs; // Number of days sampled
  int<lower = 1> n_params; // Number of model parameters
  int<lower = 1> n_difeq; // Number of differential equations in the system
  int<lower = 1> n_sample; 
  int y[n_obs]; // The binomially distributed data
  real t0; // Initial time point (zero)
  real ts[n_obs]; // Time points that were sampled
  
}

transformed data {
  real x_r[0];
  int x_i[0];
}

parameters {
  real<lower = 0> params[n_params]; // Model parameters
  real<lower = 0, upper = 1> S0; // Initial fraction of susceptible
}

transformed parameters{
  real y_hat[n_obs, n_difeq]; // Output from the ODE solver
  real y0[n_difeq]; // Initial conditions for both S and I

  y0[1] = 1 - 0.02 - 0.001;
  y0[2] = 0.02;
  y0[3] = 0;
  y0[4] = 0;
  y0[5] = 0.001;
  y0[6] = 0;
  y0[7] = 0;
  y0[8] = 0;
  
  y_hat = integrate_ode_rk45(SI, y0, t0, ts, params, x_r, x_i);
  
}

model {
  params[1] ~ normal(0.5, 0.9); //beta
  params[2] ~ normal(0.2, 0.55); //mu
  params[3] ~ normal(0, 1);  //beta_m
  params[4] ~ normal(0, 1);  //phi
  params[5] ~ normal(1, 20); //tau
  params[6] ~ normal(0, 1); //pe
  params[7] ~ normal(0, 1); //pie
  params[8] ~ normal(0, 1); //pee
  params[9] ~ normal(0.1, 0.99); //alpha
  params[10] ~ normal(3, 20); //Ts
  params[11] ~ normal(1, 20); //Ta
  params[12] ~ normal(1, 20); //Tm
  params[13] ~ normal(0.5, 8); //Ti
  S0 ~ normal(0.5, 0.5); //constrained to be 0-1.
  
  y ~ binomial(n_sample, y_hat[,5]); //y_hat[,5] are the fractions infected from the ODE solver
  
}

generated quantities {
  real R_0;
  R_0 = params[1]*params[11]*(params[9]*params[10]/params[11]*(1-params[4])+params[2]*(1-params[9]));
  
}

', 
file = "SI_fit.stan", sep="", fill=T)

# FITTING

# For stan model we need the following variables:

stan_d = list(n_obs = N,
              n_params = 13,
              n_difeq = 8,
              n_sample = 66650000,
              y = cases,
              t0 = 0,
              ts = sample_time)

# Which parameters to monitor in the model:
params_monitor = c("y_hat", "y0", "params", "R_0")

# Test / debug the model:
test = stan("SI_fit.stan",
            data = stan_d,
            pars = params_monitor,
            chains = 1, iter = 10)

# Fit and sample from the posterior
mod = stan(fit = test,
           data = stan_d,
           pars = params_monitor,
           chains = 3,
           warmup = 500,
           iter = 1500,
           control = list(adapt_delta = 0.99))

# You should do some MCMC diagnostics, including:
#traceplot(mod, pars="lp__")
#traceplot(mod, pars=c("params", "y0"))
#summary(mod)$summary[,"Rhat"]

# Extract the posterior samples to a structured list:
posts <- extract(mod)

there are 8 ODEs and 13 parameters. Note that params[4], params[6], params[7] and params[8] are probabilities and should be between 0 and 1 indeed. My aim is to given the priors estimate the posteriors. Yet when I run this I get two types of errors:

1.Chain 1: Rejecting initial value: Chain 1: Error evaluating the log probability at the initial value. Chain 1: Exception: binomial_lpmf: Probability parameter[3] is -3.6322e-06, but must be in the interval [0, 1] (in 'model25496b50bac3_SI_fit' at line 80)
this happens for other parameters too, essentially my parameters are non-negative yet stan sometimes samples negative ones.

and

  1. Chain 1: Gradient evaluation took 0.00814 seconds Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 81.4 seconds. Chain 1: Adjust your expectations accordingly!

I wonder what I am doing wrong perhaps in making my priors or stan(). Apologies in advance if my explanation is not good enough but I am a newbie on stan.

The constraints given in the parameter block do not guarantee this and initialization will often try values >1. Probability-like parameters need a separate constraint.

parameters {
  real<lower=0, upper=1> param1[n_probs];
  real<lower=0> param2[n_params - n_probs];
  ...
}
transformed parameters {
  ...
  y_hat = integrate_ode_rk45(SI, y0, t0, ts, 
            append_array(params1, params2), x_r, x_i);
}

There’s also the potential issue that the integrator is not exact. If any value goes very close to 0 or 1 the integrator may overshoot and place it slightly outside the range. In that case binomial(y_hat) will reject. In order to keep y_hat in range you may have to adjust the value after integration, something like

y_hat = 1e-6 + (1-2e-6)*y_hat;

The second message is not an error. It informs you the sampling may take several minutes. The time estimate is usually not very accurate.

1 Like

Thank you @nhuurre for your suggestions, I have implemented them as follow:

# The Stan model statement:
cat(
'
functions {
  
  real[] SI(real t,
            real[] y,
            real[] params1,
            real[] params2,
            real[] x_r,
            int[] x_i) {
      
      real dydt[8];
      
      dydt[1] = - params2[2] * params2[1] * y[1] * y[6] - params2[1] * y[1] * y[5] - params2[1] * y[8] * y[1] - params2[3] * y[7] * y[1];
      dydt[2] = params2[2] * params2[1] * y[1] * y[6] + (1 - params1[1]) * params2[1] * y[1] * y[5] + (1 - params1[1]) * params2[1] * y[8] * y[1] + (1 - params1[1]) * params2[3] * y[7] * y[1] - y[2] / params2[4];
      dydt[3] = params1[2] * params1[1] * params2[1] * y[1] * y[5] + params1[3] * params1[1] * params2[1] * y[8] * y[1] + params1[4] * params1[1] * params2[3] * y[7] * y[1] - y[3] / params2[4];
      dydt[4] = (1 - params1[2]) * params1[1] * params2[1] * y[1] * y[5] + (1 - params1[3]) * params1[1] * params2[1] * y[8] * y[1] + (1 - params1[4]) * params1[1] * params2[3] * y[7] * y[1] - y[4] / params2[4];
      dydt[5] = params2[5] * y[2] / params2[4] - y[5] / params2[6];
      dydt[6] = (1 - params2[5]) * y[2] / params2[4] - y[6] / params2[7];
      dydt[7] = y[3] / params2[4] - y[7] / params2[8];
      dydt[8] = y[4] / params2[4] - y[8] / params2[9];
      
      return dydt;
    }
  
}

data {
  int<lower = 1> n_obs; // Number of days sampled
  int<lower = 1> n_params; // Number of model parameters
  int<lower = 1> n_probs; // Number of model parameters
  int<lower = 1> n_difeq; // Number of differential equations in the system
  int<lower = 1> n_sample; 
  int y[n_obs]; // The binomially distributed data
  real t0; // Initial time point (zero)
  real ts[n_obs]; // Time points that were sampled
  
}

transformed data {
  real x_r[0];
  int x_i[0];
}

parameters {
  real<lower=0, upper=1> params1[n_probs];
  real<lower=0> params2[n_params];
  real<lower = 0, upper = 1> S0; // Initial fraction of susceptible
}

transformed parameters{
  real y_hat[n_obs, n_difeq]; // Output from the ODE solver
  real y0[n_difeq]; // Initial conditions for both S and I

  y0[1] = 1 - 0.02 - 0.001;
  y0[2] = 0.02;
  y0[3] = 0;
  y0[4] = 0;
  y0[5] = 0.001;
  y0[6] = 0;
  y0[7] = 0;
  y0[8] = 0;
  
  y_hat =integrate_ode_rk45(SI, y0, t0, ts, append_array(params1,params2), x_r, x_i);
  y_hat = 1e-6 + (1-2e-6)*y_hat;
  
}

model {
  params1[1] ~ normal(0, 1);  //phi
  params1[2] ~ normal(0, 1); //pe
  params1[3] ~ normal(0, 1); //pie
  params1[4] ~ normal(0, 1); //pee
  
  params2[1] ~ normal(0.5, 0.9); //beta
  params2[2] ~ normal(0.2, 0.55); //mu
  params2[3] ~ normal(0, 1);  //beta_m
  params2[4] ~ normal(1, 20); //tau
  params2[5] ~ normal(0.1, 0.99); //alpha
  params2[6] ~ normal(3, 20); //Ts
  params2[7] ~ normal(1, 20); //Ta
  params2[8] ~ normal(1, 20); //Tm
  params2[9] ~ normal(0.5, 8); //Ti
  
  S0 ~ normal(0.5, 0.5); //constrained to be 0-1.
  
  y ~ binomial(n_sample, y_hat[,5]); //y_hat[,5] are the fractions infected from the ODE solver
  
}

generated quantities {
  real R_0;
  R_0 = params2[1]*params2[7]*(params2[5]*params2[6]/params2[7]*(1-params1[1])+params2[2]*(1-params2[5]));
  
}

', 
file = "SI_fit.stan", sep="", fill=T)

# FITTING

# For stan model we need the following variables:

stan_d = list(n_obs = N,
              n_params = 9,
              n_probs = 4
              n_difeq = 8,
              n_sample = 66650000,
              y = cases,
              t0 = 0,
              ts = sample_time)

# Which parameters to monitor in the model:
params_monitor = c("y_hat", "y0", "params", "R_0")

# Test / debug the model:
test = stan("SI_fit.stan",
            data = stan_d,
            pars = params_monitor,
            chains = 1, iter = 10)

# Fit and sample from the posterior
mod = stan(fit = test,
           data = stan_d,
           pars = params_monitor,
           chains = 3,
           warmup = 500,
           iter = 1000,
           control = list(adapt_delta = 0.99))

# You should do some MCMC diagnostics, including:
#traceplot(mod, pars="lp__")
#traceplot(mod, pars=c("params", "y0"))
#summary(mod)$summary[,"Rhat"]

# Extract the posterior samples to a structured list:
posts <- extract(mod) 

yet now my code does not run and stuck at stan_d() I wonder if I did impose the suggestions correctly? I much appreciate your help.

Here I am adding the whole code so one can run it at ease. To reiterate, when I run it after the suggested modifications by @nhuurre the code throws the following error:

Error in close.connection(zz) : cannot close 'message' sink connection

when it gets to test = stan().

problem.R (4.8 KB)

The function signature must be

  real[] SI(real t,
            real[] y,
            real[] params,
            real[] x_r,
            int[] x_i) {

append_array concatenates the arrays into one array which you need to unpack inside the function. The code is easier to read if every parameter is given a name.

    int[] x_i) {
real dy_dt[8];

real phi = params[1]; // params1[1]
real pe = params[2]; // params1[2]
real pie = params[3]; // params1[3]
real pee = params[4]; // params1[4]
real beta = params[5]; // params2[1]
real mu = params[6]; // params2[2]
real beta_m = params[7]; // params2[3]
real tau = params[8]; // params2[4]
...

dydt[1] = -mu * beta * y[1] * y[6] - beta * y[1] * y[5]
           - beta * y[8] * y[1] - beta_m * y[7] * y[1];
dydt[2] = mu * beta * y[1] * y[6] + (1 - phi) * beta * y[1] * y[5]
            + (1 - phi) * beta * y[8] * y[1]
            + (1 - phi) * beta_m * y[7] * y[1] - y[2] / tau;
...

return dy_dt;
}

Thank you @nhuurre for your guidance and patience on this. So as you mentioned I gave the parameters their name and changed the ODEs accordingly. I also changed the model part to real names of the parameters and where it was appropriate. Yet in parameters I have:

parameters {
  real<lower=0, upper=1> params1[n_probs];
  real<lower = 0> params2[n_params n_probs]; // Model parameters
  real<lower = 0, upper = 1> S0; // Initial fraction of susceptible
} 

where param 1 are the probabilities, and 2 are the rest. I am not sure if this is in correct format as now params are all indexed from 1 to 13, what I mean I am not sure this can distinguish between probabilities and other parameters, am I missing a point here?

when I run the code I get

Error in close.connection(zz) : cannot close 'message' sink connection

which I presume because my stan part of code it not quite correct. I am attaching the new modification so one can see it at ease. Thanks in advance for your help.

problem2.R (4.6 KB)

That error message is rather unhelpful. IIRC some previous version of RStan had a bug that caused it to discard the errors. If you don’t have the latest RStan can you upgrade? Or maybe install CmdStanR? Anyway, looks like the syntax error is this line

  real<lower = 0> params2[n_params n_probs]; // Model parameters

as there should be a minus sign between n_params and n_probs. But your model requires exactly 13 parameters anyway I’d say just hardcode the values

parameters {
  real<lower=0, upper=1> params1[4];
  real<lower = 0> params2[9]; // Model parameters
  real<lower = 0, upper = 1> S0; // Initial fraction of susceptible
} 

Thanks @nhuurre, I have had stan 2.19.0 and I upgrade it to stan 2.21.0. Now when I run it on a working example I get the following error:

Error in prep_call_sampler(object) : 
  could not find function "prep_call_sampler"

I know that prep_call_sampler is a built in function of stan so I wonder what is happening? does version 2.21 not have that?

Also adding the working example in here.
working_example.R (7.2 KB)

Sorry, you need someone who knows R to answer that. Maybe @martinmodrak could help?

Thank you @nhuurre. So I downgraded my rstan for the time being to 2.19.3. Note I am using MacOs Catalina (I am mentioning this in case @martinmodrak sees it). I can now again run the original working_example.R just fine. I changed the stan code to what you’ve guided:

# The Stan model statement:
cat(
  '
functions {
  
  real[] SI(real t,
            real[] y,
            real[] params,
            real[] x_r,
            int[] x_i) {
      
      real dydt[8];
      
    
      real phi = params[1];
      real pe = params[2];
      real pie = params[3];
      real pee = params[4]; 
  
      real beta = params[5];
      real mu = params[6]; 
      real betam = params[7]; 
      real tau = params[8]; 
      real alpha = params[9]; 
      real Ts = params[10]; 
      real Ta = params[11]; 
      real Tm = params[12]; 
      real Ti = params[13]; 
      
    dydt[1] = - mu * beta * y[1] * y[6] - beta * y[1] * y[5] - beta * y[8] * y[1] - betam * y[7] * y[1];
    dydt[2] = mu * beta * y[1] * y[6] + (1 - phi) * beta * y[1] * y[5] + (1 - phi) * beta * y[8] * y[1] + (1 - phi) * betam * y[7] * y[1] - y[2] / tau;
    dydt[3] = pe * phi * beta * y[1] * y[5] + pie * phi * beta * y[8] * y[1] + pee * phi * betam * y[7] * y[1] - y[3] / tau;
    dydt[4] = (1 - pe) * phi * beta * y[1] * y[5] + (1 - pie) * phi * beta * y[8] * y[1] + (1 - pee) * phi * betam * y[7] * y[1] - y[4] / tau;
    dydt[5] = alpha * y[2] / tau - y[5] / Ts;
    dydt[6] = (1 - alpha) * y[2] / tau - y[6] / Ta;
    dydt[7] = y[3] / tau - y[7] / Tm;
    dydt[8] = y[4] / tau - y[8] / Ti;
      
      return dydt;
    }
  
}

data {
  int<lower = 1> n_obs; // Number of days sampled
  int<lower = 1> n_params; // Number of model parameters
  int<lower = 1> n_difeq; // Number of differential equations in the system
  int<lower = 1> n_sample; 
  int y[n_obs]; // The binomially distributed data
  real t0; // Initial time point (zero)
  real ts[n_obs]; // Time points that were sampled
  
}

transformed data {
  real x_r[0];
  int x_i[0];
}

parameters {
  real<lower=0, upper=1> params1[4];
  real<lower = 0> params2[9]; // Model parameters
  real<lower = 0, upper = 1> S0; // Initial fraction of susceptible
}

transformed parameters{
  real y_hat[n_obs, n_difeq]; // Output from the ODE solver
  real y0[n_difeq]; // Initial conditions for both S and I

  y0[1] = 1 - 0.02 - 0.001;
  y0[2] = 0.02;
  y0[3] = 0;
  y0[4] = 0;
  y0[5] = 0.001;
  y0[6] = 0;
  y0[7] = 0;
  y0[8] = 0;
  
  y_hat = integrate_ode_rk45(SI, y0, t0, ts, append_array(params1, params2), x_r, x_i);
  y_hat = 1e-6 + (1-2e-6)*y_hat;
  
}

model {
  phi ~ normal(0, 1);  //phi
  pe ~ normal(0, 1); //pe
  pie ~ normal(0, 1); //pie
  pee ~ normal(0, 1); //pee
  
  beta ~ normal(0.5, 0.9); //beta
  mu ~ normal(0.2, 0.55); //mu
  betam ~ normal(0, 1);  //beta_m
  tau ~ normal(1, 20); //tau
  alpha ~ normal(0.1, 0.99); //alpha
  Ts ~ normal(3, 20); //Ts
  Ta ~ normal(1, 20); //Ta
  Tm ~ normal(1, 20); //Tm
  Ti ~ normal(0.5, 8); //Ti
  S0 ~ normal(0.5, 0.5); //constrained to be 0-1.
  
  y ~ binomial(n_sample, y_hat[,5]); //y_hat[,5] are the fractions infected from the ODE solver
  
}

generated quantities {
  real R_0; 
  R_0 = beta * Ta * (alpha * Ts * (1 - phi) / Ta + mu * (1 - alpha));
  
}

', 
file = "SI_fit.stan", sep="", fill=T)

# FITTING

# For stan model we need the following variables:

stan_d = list(n_obs = N,
              n_params = 13,
              n_difeq = 8,
              n_sample = 66650000,
              y = cases,
              t0 = 0,
              ts = sample_time)

# Which parameters to monitor in the model:
params_monitor = c("y_hat", "y0", "params", "R_0")

# Test / debug the model:
test = stan("SI_fit.stan",
            data = stan_d,
            pars = params_monitor,
            chains = 1, iter = 10)

# Fit and sample from the posterior
mod = stan(fit = test,
           data = stan_d,
           pars = params_monitor,
           chains = 3,
           warmup = 500,
           iter = 1000,
           control = list(adapt_delta = 0.99))

# You should do some MCMC diagnostics, including:
#traceplot(mod, pars="lp__")
#traceplot(mod, pars=c("params", "y0"))
#summary(mod)$summary[,"Rhat"]

# Extract the posterior samples to a structured list:
posts <- extract(mod)

as you can see in data part I have:
int<lower = 1> n_params; // Number of model parameters
later I have

    stan_d = list(n_obs = N,
                  n_params = 13,
                  n_difeq = 8,
                  n_sample = 66650000,
                  y = cases,
                  t0 = 0,
                  ts = sample_time)

so n_params is 13. Now my question is in parameters we define:

parameters {
  real<lower=0, upper=1> params1[4];
  real<lower = 0> params2[9]; // Model parameters
  real<lower = 0, upper = 1> S0; // Initial fraction of susceptible
}

we namely have 4 params1 and 9 params2. But in stan_d = list() we only define n_params=13 is this not causing issue? I wonder if this is the reason I can not run the code. Namely, there are 3 names around params, params1 and params2.

@nhuurre when I run debug(rstan::stanc) I get the following which might help:

function (file, model_code = "", model_name = "anon_model", 
  verbose = FALSE, obfuscate_model_name = TRUE, allow_undefined = FALSE, 
  isystem = c(if (!missing(file)) dirname(file), getwd())) 
{
  model_name2 <- deparse(substitute(model_code))
  if (is.null(attr(model_code, "model_name2"))) 
    attr(model_code, "model_name2") <- model_name2
  model_code <- get_model_strcode(file, model_code)
  if (missing(model_name) || is.null(model_name)) 
    model_name <- attr(model_code, "model_name2")
  if (verbose) 
    cat("\nTRANSLATING MODEL '", model_name, "' FROM Stan CODE TO C++ CODE NOW.\n", 
      sep = "")
  SUCCESS_RC <- 0
  EXCEPTION_RC <- -1
  PARSE_FAIL_RC <- -2
  model_cppname <- legitimate_model_name(model_name, obfuscate_name = obfuscate_model_name)
  tf <- tempfile(fileext = ".parser")
  zz <- base::file(tf, open = "wt")
  on.exit(close(zz), add = TRUE)
  sink(zz, type = "message")
  r <- .Call(CPP_stanc280, model_code, model_cppname, allow_undefined, 
    isystem)
  sink(type = "message")
  close(zz)
  on.exit(NULL)
  r$model_name <- model_name
  r$model_code <- model_code
  if (is.null(r)) {
    stop(paste("failed to run stanc for model '", model_name, 
      "' and no error message provided", sep = ""))
  }
  else if (r$status == PARSE_FAIL_RC) {
    stop(paste("failed to parse Stan model '", model_name, 
      "' and no error message provided"), sep = "")
  }
  else if (r$status == EXCEPTION_RC) {
    lapply(r$msg, function(x) message(x))
    error_msg <- paste("failed to parse Stan model '", model_name, 
      "' due to the above error.", sep = "")
    stop(error_msg)
  }
  if (r$status == SUCCESS_RC && verbose) 
    cat("successful in parsing the Stan model '", model_name, 
      "'.\n", sep = "")
  msg <- readLines(tf)
  msg <- grep("Unknown variable", msg, value = TRUE, invert = TRUE)
  msg <- grep("aliasing", msg, value = TRUE, invert = TRUE)
  if (length(msg) > 2L) {
    cat(msg, sep = "\n")
  }
  else {
    try(file.remove(tf), silent = TRUE)
  }
  r$status = !as.logical(r$status)
  return(r)
}

and then

function (file, model_name = "anon_model", model_code = "", 
  stanc_ret = NULL, boost_lib = NULL, eigen_lib = NULL, save_dso = TRUE, 
  verbose = FALSE, auto_write = rstan_options("auto_write"), 
  obfuscate_model_name = TRUE, allow_undefined = FALSE, includes = NULL, 
  isystem = c(if (!missing(file)) dirname(file), getwd())) 
{
  if (is.null(stanc_ret)) {
    model_name2 <- deparse(substitute(model_code))
    if (is.null(attr(model_code, "model_name2"))) 
      attr(model_code, "model_name2") <- model_name2
    if (missing(model_name)) 
      model_name <- NULL
    if (missing(file)) {
      tf <- tempfile()
      writeLines(model_code, con = tf)
      file <- file.path(dirname(tf), paste0(tools::md5sum(tf), 
        ".stan"))
      if (!file.exists(file)) 
        file.rename(from = tf, to = file)
      else file.remove(tf)
    }
    else file <- normalizePath(file)
    stanc_ret <- stanc(file = file, model_code = model_code, 
      model_name = model_name, verbose = verbose, obfuscate_model_name = obfuscate_model_name, 
      allow_undefined = allow_undefined, isystem = isystem)
    model_re <- "(^[[:alnum:]]{2,}.*$)|(^[A-E,G-S,U-Z,a-z].*$)|(^[F,T].+)"
    if (!is.null(model_name)) 
      if (!grepl(model_re, model_name)) 
        stop("model name must match ", model_re)
    S4_objects <- apropos(model_re, mode = "S4", ignore.case = FALSE)
    if (length(S4_objects) > 0) {
      e <- environment()
      stanfits <- sapply(mget(S4_objects, envir = e, inherits = TRUE), 
        FUN = is, class2 = "stanfit")
      stanmodels <- sapply(mget(S4_objects, envir = e, 
        inherits = TRUE), FUN = is, class2 = "stanmodel")
      if (any(stanfits)) 
        for (i in names(which(stanfits))) {
          obj <- get_stanmodel(get(i, envir = e, inherits = TRUE))
          if (identical(obj@model_code[1], stanc_ret$model_code[1])) 
            return(obj)
        }
      if (any(stanmodels)) 
        for (i in names(which(stanmodels))) {
          obj <- get(i, envir = e, inherits = TRUE)
          if (identical(obj@model_code[1], stanc_ret$model_code[1])) 
            return(obj)
        }
    }
    mtime <- file.info(file)$mtime
    file.rds <- gsub("stan$", "rds", file)
    md5 <- tools::md5sum(file)
    if (!file.exists(file.rds)) {
      file.rds <- file.path(tempdir(), paste0(md5, ".rds"))
    }
    if (!file.exists(file.rds) || (mtime.rds <- file.info(file.rds)$mtime) < 
      as.POSIXct(packageDescription("rstan")$Date) || 
      !is(obj <- readRDS(file.rds), "stanmodel") || !is_sm_valid(obj) || 
      (!identical(stanc_ret$model_code, obj@model_code) && 
        is.null(message("hash mismatch so recompiling; make sure Stan code ends with a blank line"))) || 
      avoid_crash(obj@dso@.CXXDSOMISC$module) && is.null(message("recompiling to avoid crashing R session"))) {
    }
    else return(invisible(obj))
  }
  if (!is.list(stanc_ret)) {
    stop("stanc_ret needs to be the returned object from stanc.")
  }
  m <- match(c("cppcode", "model_name", "status"), names(stanc_ret))
  if (any(is.na(m))) {
    stop("stanc_ret does not have element `cppcode', `model_name', and `status'")
  }
  else {
    if (!stanc_ret$status) 
      stop("stanc_ret is not a successfully returned list from stanc")
  }
  if (.Platform$OS.type != "windows") {
    CXX <- get_CXX()
    if (!is.null(attr(CXX, "status")) || nchar(CXX) == 0) {
      WIKI <- "https://github.com/stan-dev/rstan/wiki/RStan-Getting-Started"
      warning(paste("C++ compiler not found on system. If absent, see\n", 
        WIKI))
    }
    else if (grepl("69", CXX, fixed = TRUE)) 
      warning("You may need to launch Xcode once to accept its license")
  }
  else CXX <- "g++"
  model_cppname <- stanc_ret$model_cppname
  model_name <- stanc_ret$model_name
  model_code <- stanc_ret$model_code
  model_cppcode <- stanc_ret$cppcode
  inc <- paste("#define STAN__SERVICES__COMMAND_HPP", "#include <boost/integer/integer_log2.hpp>\n", 
    "#include <rstan/rstaninc.hpp>\n", if (is.null(includes)) 
      model_cppcode
    else sub("(class[[:space:]]+[A-Za-z_][A-Za-z0-9_]*[[:space:]]*)", 
      paste(includes, "\\1"), model_cppcode), get_Rcpp_module_def_code(model_cppname), 
    sep = "")
  if (verbose && interactive()) 
    cat("COMPILING THE C++ CODE FOR MODEL '", model_name, 
      "' NOW.\n", sep = "")
  if (verbose) 
    cat(system_info(), "\n")
  if (!is.null(boost_lib)) {
    old.boost_lib <- rstan_options(boost_lib = boost_lib)
    on.exit(rstan_options(boost_lib = old.boost_lib))
  }
  if (!file.exists(rstan_options("boost_lib"))) 
    stop("Boost not found; call install.packages('BH')")
  if (!is.null(eigen_lib)) {
    old.eigen_lib <- rstan_options(eigen_lib = eigen_lib)
    on.exit(rstan_options(eigen_lib = old.eigen_lib), add = TRUE)
  }
  if (!file.exists(rstan_options("eigen_lib"))) 
    stop("Eigen not found; call install.packages('RcppEigen')")
  dso <- cxxfunctionplus(signature(), body = paste(" return Rcpp::wrap(\"", 
    model_name, "\");", sep = ""), includes = inc, plugin = "rstan", 
    save_dso = save_dso | auto_write, module_name = paste("stan_fit4", 
      model_cppname, "_mod", sep = ""), verbose = verbose)
  if (FALSE && grepl("#include", model_code, fixed = TRUE)) {
    model_code <- scan(text = model_code, what = character(), 
      sep = "\n", quiet = TRUE)
    model_code <- gsub("#include /", "#include ", model_code, 
      fixed = TRUE)
    model_code <- gsub("#include (.*$)", "#include \"\\1\"", 
      model_code)
    unprocessed <- tempfile(fileext = ".stan")
    processed <- tempfile(fileext = ".stan")
    on.exit(file.remove(c(unprocessed, processed)))
    writeLines(model_code, con = unprocessed)
    ARGS <- paste("-E -nostdinc -x c++ -P -C", paste("-I", 
      isystem, " ", collapse = ""), "-o", processed, unprocessed)
    pkgbuild::with_build_tools(system2(CXX, args = ARGS), 
      required = rstan_options("required") && identical(Sys.getenv("WINDOWS"), 
        "TRUE") && !identical(Sys.getenv("R_PACKAGE_SOURCE"), 
        ""))
    if (file.exists(processed)) 
      model_code <- paste(readLines(processed), collapse = "\n")
  }
  obj <- new("stanmodel", model_name = model_name, model_code = model_code, 
    dso = dso, mk_cppmodule = mk_cppmodule, model_cpp = list(model_cppname = model_cppname, 
      model_cppcode = model_cppcode))
  if (missing(file) || (file.access(dirname(file), mode = 2) != 
    0) || !isTRUE(auto_write)) {
    tf <- tempfile()
    writeLines(model_code, con = tf)
    file <- file.path(tempdir(), paste0(tools::md5sum(tf), 
      ".stan"))
    if (!file.exists(file)) 
      file.rename(from = tf, to = file)
    else file.remove(tf)
    saveRDS(obj, file = gsub("stan$", "rds", file))
  }
  else if (isTRUE(auto_write)) {
    file <- gsub("stan$", "rds", file)
    if (file.exists(file)) {
      rds <- try(readRDS(file), silent = TRUE)
      if (!is(rds, "stanmodel")) 
        warning(rds, " exists but is not a 'stanmodel' so not overwriting")
      else saveRDS(obj, file = file)
    }
    else saveRDS(obj, file = file)
  }
  invisible(obj)
}

yet I am not sure how to interpret these.