casadi_rosenbrock.hpp
1 //
2 // MIT No Attribution
3 //
4 // Copyright (C) 2010-2026 Joel Andersson, Joris Gillis, Moritz Diehl, KU Leuven.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of this
7 // software and associated documentation files (the "Software"), to deal in the Software
8 // without restriction, including without limitation the rights to use, copy, modify,
9 // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13 // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
16 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 //
19 
20 // Rosenbrock-Wanner integrator for M y' = F(t, y), see casadi_ivp.hpp
21 // Step: (M/(h gamma) - J) U_i = F(t0 + alpha_i h, y0 + sum_j a_ij U_j) + sum_j (c_ij/h) M U_j
22 // + gamma_i h dF/dt, y1 = y0 + sum_i m_i U_i, error sum_i m_err_i U_i
23 // Steps depend on the nominal entries only: sensitivities are exact derivatives of the scheme
24 
25 // C-REPLACE "fabs" "casadi_fabs"
26 // C-REPLACE "static_cast<T1>" "(casadi_real) "
27 // C-REPLACE "static_cast<casadi_int*>(0)" "0"
28 // C-REPLACE "casadi_ivp_prob<T1>" "struct casadi_ivp_prob"
29 // C-REPLACE "casadi_ivp_data<T1>" "struct casadi_ivp_data"
30 
31 // SYMBOL "rosenbrock_prob"
32 template<typename T1>
34  // Shared problem structure
36  // Diagonal coefficient
37  T1 gamma;
38  // Method coefficients, transformed form (a, alpha, m, m_err: see ivp): c strictly lower
39  // triangular, row-major, sums gamma_i of the rows of Gamma
40  const T1 *c, *gamma_sum;
41  // Iteration matrix M/(h gamma) - J: sparsity, positions of ODE_X, ALG_X, ODE_Z, ALG_Z, diag
42  const casadi_int *sp_iter, *iter_map;
43  // Sparse QR of the iteration matrix and of d(alg)/dz
44  const casadi_int *sp_iter_v, *sp_iter_r, *iter_prinv, *iter_pc;
45  const casadi_int *sp_alg_v, *sp_alg_r, *alg_prinv, *alg_pc;
46  // Consistent initialization: tolerance on scaled Newton step, iteration limit
48  casadi_int init_max_iter;
49  // Derived: nonzeros of the iteration matrix and of the QR factors
51  // Derived: length of the work vectors
52  casadi_int nv, n_qr_w;
53 };
54 // C-REPLACE "casadi_rosenbrock_prob<T1>" "struct casadi_rosenbrock_prob"
55 
56 // SYMBOL "rosenbrock_setup"
57 template<typename T1>
58 void casadi_rosenbrock_setup(casadi_rosenbrock_prob<T1>* rp) {
59  const casadi_ivp_prob<T1>* p = rp->ivp;
60  casadi_int n1 = p->nx1 + p->nz1;
61  rp->nnz_iter = casadi_ivp_nnz(rp->sp_iter);
62  rp->nnz_iter_v = casadi_ivp_nnz(rp->sp_iter_v);
63  rp->nnz_iter_r = casadi_ivp_nnz(rp->sp_iter_r);
64  rp->nnz_alg_v = p->nz1 > 0 ? casadi_ivp_nnz(rp->sp_alg_v) : 0;
65  rp->nnz_alg_r = p->nz1 > 0 ? casadi_ivp_nnz(rp->sp_alg_r) : 0;
66  // Work vectors: forward and adjoint vectors with all directions
67  rp->nv = p->ny;
68  if (p->nr + p->nrp + p->nru > rp->nv) rp->nv = p->nr + p->nrp + p->nru;
69  if (n1 * p->nadj * (1 + p->nfwd) > rp->nv) rp->nv = n1 * p->nadj * (1 + p->nfwd);
70  // Work vector of the sparse QR: extended number of rows
71  rp->n_qr_w = rp->sp_iter_v[0];
72  if (p->nz1 > 0 && rp->sp_alg_v[0] > rp->n_qr_w) rp->n_qr_w = rp->sp_alg_v[0];
73 }
74 
75 // SYMBOL "rosenbrock_next_t"
76 typedef enum {
77  // Phases: each one consumes the result of the previously requested task
78  ROSENBROCK_INIT_BEGIN = IVP_NUM_ENTRY,
79  ROSENBROCK_INIT_LINEARIZE,
80  ROSENBROCK_INIT_NEWTON_STEP,
81  ROSENBROCK_INIT_SENS_RHS,
82  ROSENBROCK_INIT_SENS,
83  ROSENBROCK_INIT_END,
84  ROSENBROCK_STEP_BEGIN,
85  ROSENBROCK_STEP_SIZE,
86  ROSENBROCK_STEP_INITIAL_SIZE,
87  ROSENBROCK_STEP_LINEARIZE,
88  ROSENBROCK_STEP_FACTORIZE,
89  ROSENBROCK_STEP_REPLAY,
90  ROSENBROCK_STAGE_SOLVE,
91  ROSENBROCK_STEP_CHECK,
92  ROSENBROCK_STEP_EVENT,
93  ROSENBROCK_OUTPUT_CORRECT,
94  ROSENBROCK_BACK_BEGIN,
95  ROSENBROCK_BACK_INIT_SOLVE,
96  ROSENBROCK_BACK_INIT_END,
97  ROSENBROCK_BACK_ADJ_BEGIN,
98  ROSENBROCK_BACK_ADJ_STAGE,
99  ROSENBROCK_BACK_ADJ_SPREAD,
100  ROSENBROCK_BACK_STEP_END,
101  ROSENBROCK_IMPULSE_LINEARIZE,
102  ROSENBROCK_IMPULSE_CORRECT,
103  ROSENBROCK_IMPULSE_END
104 } casadi_rosenbrock_next_t;
105 
106 // C-REPLACE "casadi_rosenbrock_data<T1>" "struct casadi_rosenbrock_data"
107 // SYMBOL "rosenbrock_data"
108 template<typename T1>
110  // Problem structure
112  // Method data of the nominal integration whose steps are replayed (or null)
114  // h * gamma, time derivative of F
116  T1* dfdt;
117  // Iteration matrix and its QR factors, QR factors of d(alg)/dz
119  // Work vectors of length nv
120  T1 *v1, *v2;
121  // Consistent initialization pending, Newton iteration
123  casadi_int init_iter;
124 };
125 
126 // SYMBOL "rosenbrock_work"
127 template<typename T1>
128 void casadi_rosenbrock_work(const casadi_rosenbrock_prob<T1>* rp, casadi_int* sz_arg,
129  casadi_int* sz_res, casadi_int* sz_iw, casadi_int* sz_w) {
130  const casadi_ivp_prob<T1>* p = rp->ivp;
131  casadi_int n1 = p->nx1 + p->nz1;
132  // dF/dt
133  *sz_w += p->ny;
134  // Iteration matrix, QR factors of it and of d(alg)/dz, QR work vector
135  *sz_w += rp->nnz_iter + rp->nnz_iter_v + rp->nnz_iter_r + n1;
136  *sz_w += rp->nnz_alg_v + rp->nnz_alg_r + p->nz1 + rp->n_qr_w;
137  // Work vectors
138  *sz_w += 2 * rp->nv;
139 }
140 
141 // SYMBOL "rosenbrock_set_work"
142 template<typename T1>
143 void casadi_rosenbrock_set_work(casadi_rosenbrock_data<T1>* r, const T1*** arg, T1*** res,
144  casadi_int** iw, T1** w) {
145  const casadi_rosenbrock_prob<T1>* rp = r->prob;
146  const casadi_ivp_prob<T1>* p = rp->ivp;
147  casadi_int n1 = p->nx1 + p->nz1;
148  r->dfdt = *w; *w += p->ny;
149  r->iter = *w; *w += rp->nnz_iter;
150  r->iter_v = *w; *w += rp->nnz_iter_v;
151  r->iter_r = *w; *w += rp->nnz_iter_r;
152  r->iter_beta = *w; *w += n1;
153  r->alg_v = *w; *w += rp->nnz_alg_v;
154  r->alg_r = *w; *w += rp->nnz_alg_r;
155  r->alg_beta = *w; *w += p->nz1;
156  r->qr_w = *w; *w += rp->n_qr_w;
157  r->v1 = *w; *w += rp->nv;
158  r->v2 = *w; *w += rp->nv;
159  r->nom = 0;
160 }
161 
162 // ---------------------------------------------------------------------------------------
163 // Linear algebra of the sensitivity-augmented iteration matrix
164 // ---------------------------------------------------------------------------------------
165 
166 // SYMBOL "rosenbrock_gather"
167 template<typename T1>
168 void casadi_rosenbrock_gather(const T1* x, const T1* z, casadi_int nx1, casadi_int nz1,
169  T1* v) {
170  // v = [x; z]
171  casadi_copy(x, nx1, v);
172  casadi_copy(z, nz1, v + nx1);
173 }
174 
175 // SYMBOL "rosenbrock_scatter"
176 template<typename T1>
177 void casadi_rosenbrock_scatter(const T1* v, casadi_int nx1, casadi_int nz1, T1* x, T1* z) {
178  // [x; z] = v
179  casadi_copy(v, nx1, x);
180  casadi_copy(v + nx1, nz1, z);
181 }
182 
183 // SYMBOL "rosenbrock_dfdt"
184 template<typename T1>
185 void casadi_rosenbrock_dfdt(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r) {
186  // Time derivative of [ode; alg; quad], with sensitivities, from the time columns
187  const casadi_ivp_prob<T1>* p = d->prob;
188  casadi_int k, dir, off, n1;
189  T1 one = 1;
190  casadi_clear(r->dfdt, p->ny);
191  for (k = 0; k < 3; ++k) {
192  // Empty if the right-hand side does not depend on time
193  if (p->sp_jac[IVP_ODE_T + k][1] == 0) continue;
194  off = k == 0 ? 0 : k == 1 ? p->nx : p->nx + p->nz;
195  n1 = k == 0 ? p->nx1 : k == 1 ? p->nz1 : p->nq1;
196  for (dir = -1; dir < p->nfwd; ++dir) {
197  casadi_ivp_jac_mv(d, IVP_ODE_T + k, dir, &one, r->dfdt + off + (dir + 1) * n1, 0);
198  }
199  }
200 }
201 
202 // SYMBOL "rosenbrock_factorize"
203 template<typename T1>
204 int casadi_rosenbrock_factorize(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r) {
205  // QR of M/(h gamma) - J for the nominal [x; z]; returns 1 if singular
206  const casadi_ivp_prob<T1>* p = d->prob;
207  const casadi_rosenbrock_prob<T1>* rp = r->prob;
208  casadi_int k, i, n, pos = 0;
209  const casadi_int blk[4] = {IVP_ODE_X, IVP_ALG_X, IVP_ODE_Z, IVP_ALG_Z};
210  const T1* J;
211  T1 rmin = 0;
212  casadi_clear(r->iter, rp->nnz_iter);
213  for (k = 0; k < 4; ++k) {
214  J = casadi_ivp_jac_nz(d, d->jac, blk[k], 1, 0);
215  n = casadi_ivp_nnz(p->sp_jac[blk[k]]);
216  for (i = 0; i < n; ++i) r->iter[rp->iter_map[pos++]] -= J[i];
217  }
218  for (i = 0; i < p->nx1; ++i) r->iter[rp->iter_map[pos++]] += 1 / r->h_gamma;
219  casadi_qr(rp->sp_iter, r->iter, r->qr_w, rp->sp_iter_v, r->iter_v, rp->sp_iter_r, r->iter_r,
220  r->iter_beta, rp->iter_prinv, rp->iter_pc);
221  casadi_qr_singular(&rmin, static_cast<casadi_int*>(0), r->iter_r, rp->sp_iter_r,
222  rp->iter_pc, 0.);
223  return !(rmin > 0) || !casadi_ivp_isfinite(rmin);
224 }
225 
226 // SYMBOL "rosenbrock_iter_solve"
227 template<typename T1>
228 void casadi_rosenbrock_iter_solve(casadi_rosenbrock_data<T1>* r, T1* v, casadi_int nrhs,
229  int tr) {
230  // Solve with the factorized iteration matrix (or its transpose), nrhs right-hand sides
231  const casadi_rosenbrock_prob<T1>* rp = r->prob;
232  casadi_qr_solve(v, nrhs, tr, rp->sp_iter_v, r->iter_v, rp->sp_iter_r, r->iter_r, r->iter_beta,
233  rp->iter_prinv, rp->iter_pc, r->qr_w);
234 }
235 
236 // SYMBOL "rosenbrock_solve"
237 template<typename T1>
238 void casadi_rosenbrock_solve(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r, T1* v) {
239  // A U_0 = r_0, A U_d = r_d + dJ_d U_0 (A = M/hg - J), quadratures U_q = hg (r_q + J_qy U)
240  const casadi_ivp_prob<T1>* p = d->prob;
241  casadi_int dir, n1 = p->nx1 + p->nz1;
242  T1 *u0 = r->v1, *ud, *vx = v, *vz = v + p->nx, *vq = v + p->nx + p->nz, *vqd;
243  casadi_rosenbrock_gather(vx, vz, p->nx1, p->nz1, u0);
244  casadi_rosenbrock_iter_solve(r, u0, 1, 0);
245  for (dir = 0; dir < p->nfwd; ++dir) {
246  ud = r->v2 + dir * n1;
247  casadi_rosenbrock_gather(vx + (dir + 1) * p->nx1, vz + (dir + 1) * p->nz1,
248  p->nx1, p->nz1, ud);
249  casadi_ivp_jac_mv(d, IVP_ODE_X, dir, u0, ud, 0);
250  casadi_ivp_jac_mv(d, IVP_ODE_Z, dir, u0 + p->nx1, ud, 0);
251  casadi_ivp_jac_mv(d, IVP_ALG_X, dir, u0, ud + p->nx1, 0);
252  casadi_ivp_jac_mv(d, IVP_ALG_Z, dir, u0 + p->nx1, ud + p->nx1, 0);
253  }
254  if (p->nfwd > 0) casadi_rosenbrock_iter_solve(r, r->v2, p->nfwd, 0);
255  for (dir = 0; dir < p->nfwd; ++dir) {
256  ud = r->v2 + dir * n1;
257  vqd = vq + (dir + 1) * p->nq1;
258  casadi_ivp_jac_mv(d, IVP_QUAD_X, -1, ud, vqd, 0);
259  casadi_ivp_jac_mv(d, IVP_QUAD_Z, -1, ud + p->nx1, vqd, 0);
260  casadi_ivp_jac_mv(d, IVP_QUAD_X, dir, u0, vqd, 0);
261  casadi_ivp_jac_mv(d, IVP_QUAD_Z, dir, u0 + p->nx1, vqd, 0);
262  casadi_scal(p->nq1, r->h_gamma, vqd);
263  casadi_rosenbrock_scatter(ud, p->nx1, p->nz1, vx + (dir + 1) * p->nx1,
264  vz + (dir + 1) * p->nz1);
265  }
266  casadi_ivp_jac_mv(d, IVP_QUAD_X, -1, u0, vq, 0);
267  casadi_ivp_jac_mv(d, IVP_QUAD_Z, -1, u0 + p->nx1, vq, 0);
268  casadi_scal(p->nq1, r->h_gamma, vq);
269  casadi_rosenbrock_scatter(u0, p->nx1, p->nz1, vx, vz);
270 }
271 
272 // SYMBOL "rosenbrock_solve_trans"
273 template<typename T1>
274 void casadi_rosenbrock_solve_trans(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r,
275  T1* v) {
276  // A^T mu = l + J_qy^T hg l_q, then A^T dmu_d = dl_d + J_qy^T hg dl_q + dJ_d^T [mu; hg l_q]
277  const casadi_ivp_prob<T1>* p = d->prob;
278  casadi_int a, dir, n1 = p->nx1 + p->nz1;
279  casadi_int nrx1 = p->nx1 * p->nadj, nrz1 = p->nz1 * p->nadj, nrq1 = p->nq1 * p->nadj;
280  T1 *vx = v, *vz = v + p->nrx, *vq = v + p->nrx + p->nrz;
281  T1 *mu, *mq, *dmu, *dmq, *dvx, *dvz;
282  casadi_scal(p->nrq, r->h_gamma, vq);
283  for (a = 0; a < p->nadj; ++a) {
284  mu = r->v1 + a * n1;
285  mq = vq + a * p->nq1;
286  casadi_rosenbrock_gather(vx + a * p->nx1, vz + a * p->nz1, p->nx1, p->nz1, mu);
287  casadi_ivp_jac_mv(d, IVP_QUAD_X, -1, mq, mu, 1);
288  casadi_ivp_jac_mv(d, IVP_QUAD_Z, -1, mq, mu + p->nx1, 1);
289  }
290  casadi_rosenbrock_iter_solve(r, r->v1, p->nadj, 1);
291  for (dir = 0; dir < p->nfwd; ++dir) {
292  for (a = 0; a < p->nadj; ++a) {
293  mu = r->v1 + a * n1;
294  mq = vq + a * p->nq1;
295  dmu = r->v2 + (dir * p->nadj + a) * n1;
296  dmq = vq + (dir + 1) * nrq1 + a * p->nq1;
297  dvx = vx + (dir + 1) * nrx1 + a * p->nx1;
298  dvz = vz + (dir + 1) * nrz1 + a * p->nz1;
299  casadi_rosenbrock_gather(dvx, dvz, p->nx1, p->nz1, dmu);
300  casadi_ivp_jac_mv(d, IVP_QUAD_X, -1, dmq, dmu, 1);
301  casadi_ivp_jac_mv(d, IVP_QUAD_Z, -1, dmq, dmu + p->nx1, 1);
302  casadi_ivp_jac_mv(d, IVP_QUAD_X, dir, mq, dmu, 1);
303  casadi_ivp_jac_mv(d, IVP_QUAD_Z, dir, mq, dmu + p->nx1, 1);
304  casadi_ivp_jac_mv(d, IVP_ODE_X, dir, mu, dmu, 1);
305  casadi_ivp_jac_mv(d, IVP_ALG_X, dir, mu + p->nx1, dmu, 1);
306  casadi_ivp_jac_mv(d, IVP_ODE_Z, dir, mu, dmu + p->nx1, 1);
307  casadi_ivp_jac_mv(d, IVP_ALG_Z, dir, mu + p->nx1, dmu + p->nx1, 1);
308  }
309  }
310  if (p->nfwd > 0) casadi_rosenbrock_iter_solve(r, r->v2, p->nadj * p->nfwd, 1);
311  for (a = 0; a < p->nadj; ++a) {
312  casadi_rosenbrock_scatter(r->v1 + a * n1, p->nx1, p->nz1, vx + a * p->nx1,
313  vz + a * p->nz1);
314  for (dir = 0; dir < p->nfwd; ++dir) {
315  casadi_rosenbrock_scatter(r->v2 + (dir * p->nadj + a) * n1, p->nx1, p->nz1,
316  vx + (dir + 1) * nrx1 + a * p->nx1, vz + (dir + 1) * nrz1 + a * p->nz1);
317  }
318  }
319 }
320 
321 // SYMBOL "rosenbrock_factorize_alg"
322 template<typename T1>
323 int casadi_rosenbrock_factorize_alg(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r) {
324  // QR of d(alg)/dz; returns 1 if singular
325  const casadi_rosenbrock_prob<T1>* rp = r->prob;
326  T1 rmin = 0;
327  casadi_qr(d->prob->sp_jac[IVP_ALG_Z], casadi_ivp_jac_nz(d, d->jac, IVP_ALG_Z, 1, 0),
328  r->qr_w, rp->sp_alg_v, r->alg_v, rp->sp_alg_r, r->alg_r, r->alg_beta, rp->alg_prinv,
329  rp->alg_pc);
330  casadi_qr_singular(&rmin, static_cast<casadi_int*>(0), r->alg_r, rp->sp_alg_r, rp->alg_pc,
331  0.);
332  return !(rmin > 0) || !casadi_ivp_isfinite(rmin);
333 }
334 
335 // SYMBOL "rosenbrock_alg_solve"
336 template<typename T1>
337 void casadi_rosenbrock_alg_solve(casadi_rosenbrock_data<T1>* r, T1* v, casadi_int nrhs,
338  int tr) {
339  // Solve with the factorized d(alg)/dz (or its transpose), nrhs right-hand sides
340  const casadi_rosenbrock_prob<T1>* rp = r->prob;
341  casadi_qr_solve(v, nrhs, tr, rp->sp_alg_v, r->alg_v, rp->sp_alg_r, r->alg_r, r->alg_beta,
342  rp->alg_prinv, rp->alg_pc, r->qr_w);
343 }
344 
345 // SYMBOL "rosenbrock_newton_step"
346 template<typename T1>
347 void casadi_rosenbrock_newton_step(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r,
348  T1* v) {
349  // Augmented Newton step: g_z w_0 = v_0, g_z w_d = v_d - dg_z,d w_0
350  const casadi_ivp_prob<T1>* p = d->prob;
351  casadi_int dir;
352  T1* vd;
353  casadi_rosenbrock_alg_solve(r, v, 1, 0);
354  for (dir = 0; dir < p->nfwd; ++dir) {
355  vd = v + (dir + 1) * p->nz1;
356  casadi_scal(p->nz1, -1., vd);
357  casadi_ivp_jac_mv(d, IVP_ALG_Z, dir, v, vd, 0);
358  casadi_scal(p->nz1, -1., vd);
359  }
360  if (p->nfwd > 0) casadi_rosenbrock_alg_solve(r, v + p->nz1, p->nfwd, 0);
361 }
362 
363 // SYMBOL "rosenbrock_newton_step_trans"
364 template<typename T1>
365 void casadi_rosenbrock_newton_step_trans(casadi_ivp_data<T1>* d,
366  casadi_rosenbrock_data<T1>* r, T1* v) {
367  // Transposed: g_z^T mu = v, g_z^T dmu_d = dv_d - dg_z,d^T mu, for each adjoint direction
368  const casadi_ivp_prob<T1>* p = d->prob;
369  casadi_int a, dir, nrz1 = p->nz1 * p->nadj;
370  T1 *mu, *dmu;
371  casadi_rosenbrock_alg_solve(r, v, p->nadj, 1);
372  for (dir = 0; dir < p->nfwd; ++dir) {
373  for (a = 0; a < p->nadj; ++a) {
374  mu = v + a * p->nz1;
375  dmu = v + (dir + 1) * nrz1 + a * p->nz1;
376  casadi_scal(p->nz1, -1., dmu);
377  casadi_ivp_jac_mv(d, IVP_ALG_Z, dir, mu, dmu, 1);
378  casadi_scal(p->nz1, -1., dmu);
379  }
380  }
381  if (p->nfwd > 0) casadi_rosenbrock_alg_solve(r, v + nrz1, p->nadj * p->nfwd, 1);
382 }
383 
384 // SYMBOL "rosenbrock_accum_jac_adj"
385 template<typename T1>
386 void casadi_rosenbrock_accum_jac_adj(casadi_ivp_data<T1>* d, const T1* w, const T1* u,
387  T1 coef) {
388  // jac_adj_a += w_a u^T (x, z columns), coef w_a (time column), and forward derivatives
389  const casadi_ivp_prob<T1>* p = d->prob;
390  casadi_int a, row, c, k, dir, n_row, n_col;
391  const T1 *wa, *dwa, *uc;
392  T1 one = 1;
393  for (a = 0; a < p->nadj; ++a) {
394  for (row = 0; row < 3; ++row) {
395  // Rows: ode, alg, quad
396  n_row = row == 0 ? p->nx1 : row == 1 ? p->nz1 : p->nq1;
397  wa = (row == 0 ? w : row == 1 ? w + p->nrx : w + p->nrx + p->nrz) + a * n_row;
398  for (c = 0; c < 3; ++c) {
399  // Columns: x, z, t
400  k = 3 * c + row;
401  if (casadi_ivp_nnz(p->sp_jac[k]) == 0) continue;
402  n_col = c == 0 ? p->nx1 : p->nz1;
403  uc = c == 0 ? u : u + p->nx;
404  casadi_rank1(casadi_ivp_jac_nz(d, d->jac_adj, k, p->nadj, a), p->sp_jac[k],
405  c < 2 ? one : coef, wa, c < 2 ? uc : &one);
406  for (dir = 0; dir < p->nfwd; ++dir) {
407  dwa = wa + (dir + 1) * n_row * p->nadj;
408  casadi_rank1(casadi_ivp_jac_nz(d, d->jac_adj_fwd, k, p->nadj * p->nfwd,
409  dir * p->nadj + a), p->sp_jac[k], c < 2 ? one : coef, dwa, c < 2 ? uc : &one);
410  if (c < 2) {
411  casadi_rank1(casadi_ivp_jac_nz(d, d->jac_adj_fwd, k, p->nadj * p->nfwd,
412  dir * p->nadj + a), p->sp_jac[k], one, wa, uc + (dir + 1) * n_col);
413  }
414  }
415  }
416  }
417  }
418 }
419 
420 // ---------------------------------------------------------------------------------------
421 // Consistent initialization
422 // ---------------------------------------------------------------------------------------
423 
424 // SYMBOL "rosenbrock_newton_norm"
425 template<typename T1>
426 T1 casadi_rosenbrock_newton_norm(const casadi_ivp_data<T1>* d, const T1* dz) {
427  // Weighted RMS norm of a Newton step for the error controlled algebraic states
428  const casadi_ivp_prob<T1>* p = d->prob;
429  casadi_int i;
430  T1 ri, sum = 0;
431  if (p->nz_err == 0) return 0;
432  for (i = 0; i < p->nz_err; ++i) {
433  ri = dz[i] / (p->abstol + p->reltol * fabs(d->y[p->nx + i]));
434  sum += ri * ri;
435  }
436  return sqrt(sum / static_cast<T1>(p->nz_err));
437 }
438 
439 // SYMBOL "rosenbrock_stage_rhs"
440 template<typename T1>
441 void casadi_rosenbrock_stage_rhs(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r,
442  casadi_int i) {
443  // U_i += sum_{j<i} (c_ij/h) M U_j + gamma_i h dF/dt, with U_i holding F on entry
444  const casadi_ivp_prob<T1>* p = d->prob;
445  const casadi_rosenbrock_prob<T1>* rp = r->prob;
446  casadi_int j;
447  T1 *Ui = d->U + i * p->ny, cij;
448  for (j = 0; j < i; ++j) {
449  cij = rp->c[i * p->n_stages + j] / d->h;
450  // M is the identity on x and q, zero on z
451  casadi_axpy(p->nx, cij, d->U + j * p->ny, Ui);
452  casadi_axpy(p->nq, cij, d->U + j * p->ny + p->nx + p->nz, Ui + p->nx + p->nz);
453  }
454  casadi_axpy(p->ny, rp->gamma_sum[i] * d->h, r->dfdt, Ui);
455 }
456 
457 // SYMBOL "rosenbrock_stage_request"
458 template<typename T1>
459 int casadi_rosenbrock_stage_request(casadi_ivp_data<T1>* d) {
460  // Right-hand side at the argument of the current stage
461  const casadi_ivp_prob<T1>* p = d->prob;
462  casadi_ivp_stage_argument(d, d->stage);
463  d->t_arg = d->t0 + p->alpha[d->stage] * d->h;
464  d->y_arg = d->y_stage;
465  d->res = d->U + d->stage * p->ny;
466  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_STAGE_SOLVE);
467 }
468 
469 // ---------------------------------------------------------------------------------------
470 // Forward integration and discrete adjoint
471 // ---------------------------------------------------------------------------------------
472 
473 // SYMBOL "rosenbrock"
474 template<typename T1>
475 int casadi_rosenbrock(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r);
476 
477 // SYMBOL "rosenbrock_forward"
478 template<typename T1>
479 int casadi_rosenbrock_forward(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r) {
480  // Forward integration; returns 1 if a task is requested, 0 when done or failed
481  const casadi_ivp_prob<T1>* p = d->prob;
482  const casadi_rosenbrock_prob<T1>* rp = r->prob;
483  T1 err, *v;
484  int ret;
485  switch (d->next) {
486  case IVP_ADVANCE:
487  if (d->reset) {
488  // New state or controls: consistent algebraic states, a new run of fixed steps
489  casadi_ivp_begin_run(d);
490  r->init_pending = p->nz > 0;
491  }
492  d->next = r->init_pending ? ROSENBROCK_INIT_BEGIN : ROSENBROCK_STEP_BEGIN;
493  return casadi_rosenbrock_forward(d, r);
494  // Consistent initialization: Newton's method for alg(t, x, z) = 0, x fixed
495  case ROSENBROCK_INIT_BEGIN:
496  if (d->fail) return casadi_ivp_stop(d, IVP_TAPE_FAILED);
497  if ((ret = casadi_ivp_reserve(d, IVP_RECORD_INIT, ROSENBROCK_INIT_BEGIN)) >= 0) return ret;
498  casadi_copy(d->u, p->nu, d->u_step);
499  r->init_iter = 0;
500  d->t_arg = d->t;
501  d->y_arg = d->y;
502  d->res = d->U;
503  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_INIT_LINEARIZE);
504  case ROSENBROCK_INIT_LINEARIZE:
505  if (d->fail) return casadi_ivp_stop(d, IVP_INIT_FAILED);
506  d->n_rhs++;
507  return casadi_ivp_request(d, IVP_EVAL_JAC, ROSENBROCK_INIT_NEWTON_STEP);
508  case ROSENBROCK_INIT_NEWTON_STEP:
509  if (d->fail || casadi_rosenbrock_factorize_alg(d, r)) {
510  return casadi_ivp_stop(d, IVP_INIT_FAILED);
511  }
512  d->n_jac++;
513  // z <- z - g_z^{-1} g, with sensitivities
514  v = d->U + p->nx;
515  casadi_rosenbrock_newton_step(d, r, v);
516  casadi_axpy(p->nz, -1., v, d->y + p->nx);
517  err = casadi_rosenbrock_newton_norm(d, v);
518  if (++r->init_iter > rp->init_max_iter || !casadi_ivp_isfinite(err)) {
519  return casadi_ivp_stop(d, IVP_INIT_FAILED);
520  }
521  if (err > rp->init_tol) {
522  // Next Newton iteration
523  d->res = d->U;
524  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_INIT_LINEARIZE);
525  }
526  if (p->nfwd == 0) {
527  d->next = ROSENBROCK_INIT_END;
528  return casadi_rosenbrock_forward(d, r);
529  }
530  // Consistent algebraic sensitivities at the solution (implicit function theorem)
531  return casadi_ivp_request(d, IVP_EVAL_JAC, ROSENBROCK_INIT_SENS_RHS);
532  case ROSENBROCK_INIT_SENS_RHS:
533  if (d->fail || casadi_rosenbrock_factorize_alg(d, r)) {
534  return casadi_ivp_stop(d, IVP_INIT_FAILED);
535  }
536  d->n_jac++;
537  d->res = d->U;
538  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_INIT_SENS);
539  case ROSENBROCK_INIT_SENS:
540  if (d->fail) return casadi_ivp_stop(d, IVP_INIT_FAILED);
541  d->n_rhs++;
542  // dz_d -= g_z^{-1} (g_x dx_d + g_z dz_d + g_p dp_d + g_u du_d)
543  v = d->U + p->nx + p->nz1;
544  casadi_rosenbrock_alg_solve(r, v, p->nfwd, 0);
545  casadi_axpy(p->nz1 * p->nfwd, -1., v, d->y + p->nx + p->nz1);
546  d->next = ROSENBROCK_INIT_END;
547  return casadi_rosenbrock_forward(d, r);
548  case ROSENBROCK_INIT_END:
549  r->init_pending = 0;
550  if (d->taping) {
551  d->record = IVP_RECORD_INIT;
552  casadi_ivp_tape_push(d, d->y, static_cast<T1>(0), d->t, d->t);
553  }
554  d->next = ROSENBROCK_STEP_BEGIN;
555  return casadi_rosenbrock_forward(d, r);
556  // Integrator step
557  case ROSENBROCK_STEP_BEGIN:
558  if (d->fail) return casadi_ivp_stop(d, IVP_TAPE_FAILED);
559  if (d->t >= d->t_out) {
560  if (d->pause) return casadi_ivp_stop(d, IVP_SUCCESS);
561  if (!casadi_ivp_output(d) || p->nz == 0) return casadi_ivp_stop(d, IVP_SUCCESS);
562  // Output inside the last step, algebraic states: Newton step on alg(t_out, x, z) = 0,
563  // d(alg)/dz at the step start
564  if (casadi_rosenbrock_factorize_alg(d, r)) {
565  return casadi_ivp_stop(d, IVP_EVAL_FAILED);
566  }
567  d->t_arg = d->t_out;
568  d->y_arg = d->y_out;
569  d->res = d->y_stage;
570  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_OUTPUT_CORRECT);
571  }
572  if (d->jump) {
573  // State changed by an event: restart
574  d->reset = 1;
575  d->next = IVP_ADVANCE;
576  return casadi_rosenbrock_forward(d, r);
577  }
578  if (casadi_ivp_step_limit(d)) return casadi_ivp_stop(d, IVP_MAX_NUM_STEPS);
579  if ((ret = casadi_ivp_reserve(d, IVP_RECORD_STEP, ROSENBROCK_STEP_BEGIN)) >= 0) return ret;
580  // Controls of the new step
581  casadi_copy(d->u, p->nu, d->u_step);
582  if (d->nom) {
583  // Step of the nominal integration
584  d->next = ROSENBROCK_STEP_REPLAY;
585  return casadi_rosenbrock_forward(d, r);
586  }
587  if (p->step_size > 0) {
588  d->h = d->run_h;
589  d->next = ROSENBROCK_STEP_LINEARIZE;
590  return casadi_rosenbrock_forward(d, r);
591  }
592  return casadi_ivp_request_control(d, IVP_CONTROL_SIZE, ROSENBROCK_STEP_SIZE);
593  case ROSENBROCK_STEP_SIZE:
594  if (d->h > 0) {
595  d->next = ROSENBROCK_STEP_LINEARIZE;
596  return casadi_rosenbrock_forward(d, r);
597  }
598  // Estimate from the right-hand side at the initial point
599  d->t_arg = d->t;
600  d->y_arg = d->y;
601  d->res = d->U;
602  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_STEP_INITIAL_SIZE);
603  case ROSENBROCK_STEP_INITIAL_SIZE:
604  if (d->fail) return casadi_ivp_stop(d, IVP_EVAL_FAILED);
605  d->n_rhs++;
606  return casadi_ivp_request_control(d, IVP_CONTROL_INIT, ROSENBROCK_STEP_SIZE);
607  case ROSENBROCK_STEP_LINEARIZE:
608  // Linearize at the beginning of the step
609  d->t0 = d->t;
610  casadi_copy(d->y, p->ny, d->y0);
611  d->t_arg = d->t0;
612  d->y_arg = d->y0;
613  return casadi_ivp_request(d, IVP_EVAL_JAC, ROSENBROCK_STEP_FACTORIZE);
614  case ROSENBROCK_STEP_REPLAY:
615  // Advance the nominal integration by one step; its tasks are handed to the caller
616  if (casadi_rosenbrock(d->nom, r->nom)) {
617  d->active = d->nom;
618  return 1;
619  }
620  d->active = d;
621  if (d->nom->status != IVP_SUCCESS) return casadi_ivp_stop(d, d->nom->status);
622  if (d->nom->next == IVP_DONE) return casadi_ivp_stop(d, IVP_EVAL_FAILED);
623  // Same step size, same end time
624  d->h = d->nom->h;
625  d->next = ROSENBROCK_STEP_LINEARIZE;
626  return casadi_rosenbrock_forward(d, r);
627  case ROSENBROCK_STEP_FACTORIZE:
628  if (d->fail) return casadi_ivp_stop(d, IVP_EVAL_FAILED);
629  d->n_jac++;
630  casadi_rosenbrock_dfdt(d, r);
631  r->h_gamma = d->h * rp->gamma;
632  if (casadi_rosenbrock_factorize(d, r)) {
633  // Singular iteration matrix: retry with a smaller step, if adaptive
634  if (casadi_ivp_prescribed(d)) return casadi_ivp_stop(d, IVP_EVAL_FAILED);
635  return casadi_ivp_request_control(d, IVP_CONTROL_FAIL, ROSENBROCK_STEP_CHECK);
636  }
637  d->stage = 0;
638  return casadi_rosenbrock_stage_request(d);
639  case ROSENBROCK_STAGE_SOLVE:
640  if (d->fail) {
641  // Evaluation failed: retry with a smaller step, if adaptive
642  if (casadi_ivp_prescribed(d)) return casadi_ivp_stop(d, IVP_EVAL_FAILED);
643  return casadi_ivp_request_control(d, IVP_CONTROL_FAIL, ROSENBROCK_STEP_CHECK);
644  }
645  d->n_rhs++;
646  casadi_rosenbrock_stage_rhs(d, r, d->stage);
647  casadi_rosenbrock_solve(d, r, d->U + d->stage * p->ny);
648  if (++d->stage < p->n_stages) return casadi_rosenbrock_stage_request(d);
649  // Candidate solution y = y0 + sum_i m_i U_i
650  casadi_copy(d->y0, p->ny, d->y);
651  casadi_mv_dense(d->U, p->ny, p->n_stages, p->m, d->y, 0);
652  if (!casadi_ivp_prescribed(d)) {
653  return casadi_ivp_request_control(d, IVP_CONTROL_TEST, ROSENBROCK_STEP_CHECK);
654  }
655  d->accepted = 1;
656  d->next = ROSENBROCK_STEP_CHECK;
657  return casadi_rosenbrock_forward(d, r);
658  case ROSENBROCK_STEP_CHECK:
659  if (d->status != IVP_SUCCESS) return casadi_ivp_stop(d, d->status);
660  if (!d->accepted) {
661  // Retry from t0
662  d->next = ROSENBROCK_STEP_BEGIN;
663  return casadi_rosenbrock_forward(d, r);
664  }
665  casadi_ivp_accept(d);
666  if (p->ne > 0) return casadi_ivp_request(d, IVP_EVENT, ROSENBROCK_STEP_EVENT);
667  d->next = ROSENBROCK_STEP_EVENT;
668  return casadi_rosenbrock_forward(d, r);
669  case ROSENBROCK_STEP_EVENT:
670  if (d->status != IVP_SUCCESS) return casadi_ivp_stop(d, d->status);
671  d->next = ROSENBROCK_STEP_BEGIN;
672  if (d->pause) {
673  // Hand the step to the integration that replays it
674  d->status = IVP_SUCCESS;
675  return 0;
676  }
677  return casadi_rosenbrock_forward(d, r);
678  case ROSENBROCK_OUTPUT_CORRECT:
679  if (d->fail) return casadi_ivp_stop(d, IVP_EVAL_FAILED);
680  d->n_rhs++;
681  v = d->y_stage + p->nx;
682  casadi_rosenbrock_newton_step(d, r, v);
683  casadi_axpy(p->nz, -1., v, d->y_out + p->nx);
684  return casadi_ivp_stop(d, IVP_SUCCESS);
685  default:
686  return 0;
687  }
688 }
689 
690 // SYMBOL "rosenbrock_backward"
691 template<typename T1>
692 int casadi_rosenbrock_backward(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r) {
693  // Discrete adjoint of the taped steps; returns 1 if a task is requested, 0 when done
694  const casadi_ivp_prob<T1>* p = d->prob;
695  const casadi_rosenbrock_prob<T1>* rp = r->prob;
696  casadi_int i, j, s = p->n_stages;
697  T1 cij, *rUi, *rUj;
698  switch (d->next) {
699  case IVP_RETREAT:
700  case ROSENBROCK_BACK_BEGIN:
701  if (!casadi_ivp_back_begin(d)) return 0;
702  if (d->record == IVP_RECORD_EVENT) {
703  return casadi_ivp_request(d, IVP_EVENT_ADJ, ROSENBROCK_BACK_BEGIN);
704  }
705  // Linearize at the beginning of the record
706  d->t_arg = d->t0;
707  d->y_arg = d->y0;
708  return casadi_ivp_request(d, IVP_EVAL_JAC,
709  d->record == IVP_RECORD_INIT ? ROSENBROCK_BACK_INIT_SOLVE : ROSENBROCK_BACK_ADJ_BEGIN);
710  case ROSENBROCK_BACK_INIT_SOLVE:
711  if (d->fail || casadi_rosenbrock_factorize_alg(d, r)) break;
712  // Implicit function theorem: mu = (d(alg)/dz)^{-T} zbar, xbar -= (d(alg)/dx)^T mu
713  casadi_clear(r->v1, p->nr);
714  casadi_copy(d->ry + p->nrx, p->nrz, r->v1 + p->nrx);
715  casadi_rosenbrock_newton_step_trans(d, r, r->v1 + p->nrx);
716  casadi_scal(p->nrz, -1., r->v1 + p->nrx);
717  casadi_ivp_clear_vjp(d);
718  d->w = r->v1;
719  return casadi_ivp_request(d, IVP_EVAL_VJP, ROSENBROCK_BACK_INIT_END);
720  case ROSENBROCK_BACK_INIT_END:
721  if (d->fail) break;
722  d->n_vjp++;
723  casadi_ivp_add_vjp(d, d->ry);
724  // The algebraic adjoint has been propagated into the differential states
725  casadi_clear(d->ry + p->nrx, p->nrz);
726  d->t = d->t0;
727  d->next = ROSENBROCK_BACK_BEGIN;
728  return casadi_rosenbrock_backward(d, r);
729  case ROSENBROCK_BACK_ADJ_BEGIN:
730  if (d->fail) break;
731  r->h_gamma = d->h * rp->gamma;
732  if (casadi_rosenbrock_factorize(d, r)) break;
733  casadi_ivp_back_step_begin(d);
734  d->next = ROSENBROCK_BACK_ADJ_STAGE;
735  return casadi_rosenbrock_backward(d, r);
736  case ROSENBROCK_BACK_ADJ_SPREAD:
737  // Adjoint of y0 + sum_j a_ij U_j and sum_j (c_ij/h) M U_j to y0 and earlier stages
738  if (d->fail) break;
739  d->n_vjp++;
740  i = d->stage;
741  rUi = d->rU + i * p->nr;
742  casadi_ivp_add_vjp(d, d->ry);
743  for (j = 0; j < i; ++j) {
744  rUj = d->rU + j * p->nr;
745  casadi_axpy(p->nrx, p->a[i * s + j], d->vjp_x, rUj);
746  casadi_axpy(p->nrz, p->a[i * s + j], d->vjp_z, rUj + p->nrx);
747  cij = rp->c[i * s + j] / d->h;
748  casadi_axpy(p->nrx, cij, rUi, rUj);
749  casadi_axpy(p->nrq, cij, rUi + p->nrx + p->nrz, rUj + p->nrx + p->nrz);
750  }
751  d->next = ROSENBROCK_BACK_ADJ_STAGE;
752  return casadi_rosenbrock_backward(d, r);
753  case ROSENBROCK_BACK_ADJ_STAGE:
754  if (d->stage == 0) {
755  // Contribution through J(t0, y0), dF/dt(t0, y0)
756  casadi_ivp_clear_vjp(d);
757  d->t_arg = d->t0;
758  d->y_arg = d->y0;
759  return casadi_ivp_request(d, IVP_EVAL_JAC_ADJ, ROSENBROCK_BACK_STEP_END);
760  }
761  // Previous stage: rbar_i = A^{-T} Ubar_i, then through J, dF/dt at y0 and F at the stage
762  i = --d->stage;
763  rUi = d->rU + i * p->nr;
764  casadi_rosenbrock_solve_trans(d, r, rUi);
765  casadi_rosenbrock_accum_jac_adj(d, rUi, d->U + i * p->ny, rp->gamma_sum[i] * d->h);
766  casadi_ivp_stage_argument(d, i);
767  casadi_ivp_clear_vjp(d);
768  d->t_arg = d->t0 + p->alpha[i] * d->h;
769  d->y_arg = d->y_stage;
770  d->w = rUi;
771  return casadi_ivp_request(d, IVP_EVAL_VJP, ROSENBROCK_BACK_ADJ_SPREAD);
772  case ROSENBROCK_BACK_STEP_END:
773  if (d->fail) break;
774  casadi_ivp_add_vjp(d, d->ry);
775  casadi_clear(d->jac_adj, p->nnz_jac * p->nadj * (1 + p->nfwd));
776  d->t = d->t0;
777  d->next = ROSENBROCK_BACK_BEGIN;
778  return casadi_rosenbrock_backward(d, r);
779  // Adjoint seed of the output at t_seed
780  case IVP_IMPULSE:
781  if (!casadi_ivp_impulse_begin(d)) return 0;
782  // Output inside the pending step
783  if (p->nz == 0) {
784  casadi_ivp_seed_stages(d);
785  return casadi_ivp_stop(d, IVP_SUCCESS);
786  }
787  // Adjoint of the Newton step on the algebraic states, as in the forward integration
788  d->t_arg = d->t0;
789  d->y_arg = d->y0;
790  return casadi_ivp_request(d, IVP_EVAL_JAC, ROSENBROCK_IMPULSE_LINEARIZE);
791  case ROSENBROCK_IMPULSE_LINEARIZE:
792  if (d->fail || casadi_rosenbrock_factorize_alg(d, r)) break;
793  d->t_arg = d->t_seed;
794  d->y_arg = d->y_out;
795  d->res = d->y_stage;
796  return casadi_ivp_request(d, IVP_EVAL_RHS, ROSENBROCK_IMPULSE_CORRECT);
797  case ROSENBROCK_IMPULSE_CORRECT:
798  // z_out = z - G^{-1} alg with G = d(alg)/dz at the step start: dz = G^{-1} alg,
799  // mu = G^{-T} zbar, Gbar = mu dz^T, (x, z, p, u)bar -= d(alg)/d(x, z, p, u)^T mu
800  if (d->fail) break;
801  casadi_rosenbrock_newton_step(d, r, d->y_stage + p->nx);
802  casadi_clear(r->v1, p->nr);
803  casadi_copy(d->seed + p->nrx, p->nrz, r->v1 + p->nrx);
804  casadi_rosenbrock_newton_step_trans(d, r, r->v1 + p->nrx);
805  casadi_clear(r->v2, p->ny);
806  casadi_copy(d->y_stage + p->nx, p->nz, r->v2 + p->nx);
807  casadi_rosenbrock_accum_jac_adj(d, r->v1, r->v2, 0.);
808  casadi_scal(p->nrz, -1., r->v1 + p->nrx);
809  casadi_ivp_clear_vjp(d);
810  d->w = r->v1;
811  return casadi_ivp_request(d, IVP_EVAL_VJP, ROSENBROCK_IMPULSE_END);
812  case ROSENBROCK_IMPULSE_END:
813  if (d->fail) break;
814  d->n_vjp++;
815  casadi_axpy(p->nrx, 1., d->vjp_x, d->seed);
816  casadi_axpy(p->nrz, 1., d->vjp_z, d->seed + p->nrx);
817  casadi_axpy(p->nrp, 1., d->vjp_p, d->adj_p);
818  // Control adjoints belong to the output interval of the step
819  casadi_axpy(p->nru, 1., d->vjp_u, d->ru_step);
820  casadi_ivp_seed_stages(d);
821  return casadi_ivp_stop(d, IVP_SUCCESS);
822  default:
823  return 0;
824  }
825  return casadi_ivp_stop(d, IVP_EVAL_FAILED);
826 }
827 
828 template<typename T1>
829 int casadi_rosenbrock(casadi_ivp_data<T1>* d, casadi_rosenbrock_data<T1>* r) {
830  // Reverse communication: returns 1 while a task in d->task is to be carried out
831  if (d->next == IVP_IMPULSE || d->next == IVP_RETREAT || d->next >= ROSENBROCK_BACK_BEGIN) {
832  return casadi_rosenbrock_backward(d, r);
833  }
834  return casadi_rosenbrock_forward(d, r);
835 }
void casadi_scal(casadi_int n, T1 alpha, T1 *x)
SCAL: x <- alpha*x.
T sum(const std::vector< T > &values)
sum
casadi_ivp_data< T1 > * active
Definition: casadi_ivp.hpp:191
casadi_int n_jac
Definition: casadi_ivp.hpp:267
const T1 * w
Definition: casadi_ivp.hpp:206
casadi_ivp_flag_t status
Definition: casadi_ivp.hpp:201
casadi_ivp_record_t record
Definition: casadi_ivp.hpp:245
const casadi_ivp_prob< T1 > * prob
Definition: casadi_ivp.hpp:189
casadi_int n_rhs
Definition: casadi_ivp.hpp:267
const T1 * y_arg
Definition: casadi_ivp.hpp:206
casadi_int next
Definition: casadi_ivp.hpp:200
const T1 * u
Definition: casadi_ivp.hpp:214
casadi_ivp_data< T1 > * nom
Definition: casadi_ivp.hpp:193
casadi_int stage
Definition: casadi_ivp.hpp:221
casadi_int n_vjp
Definition: casadi_ivp.hpp:267
casadi_int nnz_jac
Definition: casadi_ivp.hpp:148
casadi_int nrp
Definition: casadi_ivp.hpp:145
casadi_int nz_err
Definition: casadi_ivp.hpp:130
const T1 * m
Definition: casadi_ivp.hpp:118
casadi_int nx
Definition: casadi_ivp.hpp:145
const casadi_int * sp_jac[IVP_NUM_JAC]
Definition: casadi_ivp.hpp:123
casadi_int ny
Definition: casadi_ivp.hpp:145
const T1 * alpha
Definition: casadi_ivp.hpp:118
casadi_int nru
Definition: casadi_ivp.hpp:145
casadi_int nrq
Definition: casadi_ivp.hpp:145
casadi_int nr
Definition: casadi_ivp.hpp:145
casadi_int nrz
Definition: casadi_ivp.hpp:145
casadi_int nrx
Definition: casadi_ivp.hpp:145
casadi_int nz
Definition: casadi_ivp.hpp:145
casadi_int nz1
Definition: casadi_ivp.hpp:112
casadi_int nfwd
Definition: casadi_ivp.hpp:114
casadi_int nq
Definition: casadi_ivp.hpp:145
casadi_int nx1
Definition: casadi_ivp.hpp:112
casadi_int nadj
Definition: casadi_ivp.hpp:114
const T1 * a
Definition: casadi_ivp.hpp:118
casadi_int ne
Definition: casadi_ivp.hpp:140
casadi_int nq1
Definition: casadi_ivp.hpp:112
casadi_int n_stages
Definition: casadi_ivp.hpp:117
casadi_int nu
Definition: casadi_ivp.hpp:145
const casadi_rosenbrock_prob< T1 > * prob
casadi_rosenbrock_data< T1 > * nom
const casadi_int * sp_alg_r
const casadi_int * sp_iter_v
const casadi_int * iter_pc
const casadi_int * sp_iter
const casadi_ivp_prob< T1 > * ivp
const casadi_int * alg_pc
const casadi_int * iter_prinv
const casadi_int * sp_iter_r
const casadi_int * alg_prinv
const casadi_int * iter_map
const casadi_int * sp_alg_v