Hi!
I think I need to revise my suggestion of the jacobian_ode function as the current design would need to modify the AD stack during ODE integration even if a user supplies analytic Jacobians if I am not wrong. So here is what would happen now:
In the ode_rhs_sensitivity operator() function Jy would be obtained by doing something like
// use Jy
vector Jy(N_ * N_);
const vector y_v(y, y + N_);
jacobian_ode(rhs_, y_v, theta_d_, ydot, Jy.begin());
The problem is that creating y_v from y (which is an iterator into a double only vector) will inadvertly access and modify the AD stack which I really do not want to happen for the reason that this would make trivial parallelization very hard. So to get that the ODE integration is a double only operation whenever the user supplies an analytic Jacobian we may not rely on function overloading. Moreover, we wanted to mark these jacobians with a type which express that they are analytic or use AD, so we should probably use
template
struct jacobian_ode_initials {typedef boost::true_type use_AD;
void operator()(const ode_rhs rhs&,
const vector& y_d,
const vector& theta_d,
vector::iterator ydot,
vector::iterator Jy) {
// use AD to calculate Jy and stream out to Jy. Will write NxN
// elements (N=length of y_d vector)
}
};// this one corresponds to Jtheta
template
struct jacobian_ode_params {typedef boost::true_type use_AD;
void operator()(const ode_rhs&,
const vector< double >& y_d,
const vector& theta_d,
vector::iterator ydot,
vector::iterator Jtheta) {
// use AD to calculate Jtheta
}
};
This version has double only arguments. The access to the AD stack will only ever happen inside these functions and should a user specify these functions to provide analytic Jacobians, then the ODE integration will not touch the AD stack. I hope that makes sense, if so I will update the dummy code on the wiki.
One more question wrt to what is to come: In the future we would certainly like that users can specify the Jacobians inside the Stan language. For that purpose is it OK to make both jacobian_ode_* a functor object? Anything else to consider in this regard?
Best,
Sebastian