gsl_ode-initval__rk8pd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /* ode-initval/rk8pd.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. /* Runge-Kutta 8(9), Prince-Dormand
  20. *
  21. * High Order Embedded Runge-Kutta Formulae
  22. * P.J. Prince and J.R. Dormand
  23. * J. Comp. Appl. Math.,7, pp. 67-75, 1981
  24. */
  25. /* Author: G. Jungman
  26. */
  27. #include "gsl__config.h"
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "gsl_errno.h"
  31. #include "gsl_odeiv.h"
  32. #include "gsl_ode-initval__odeiv_util.h"
  33. /* Prince-Dormand constants */
  34. static const double Abar[] = {
  35. 14005451.0 / 335480064.0,
  36. 0.0,
  37. 0.0,
  38. 0.0,
  39. 0.0,
  40. -59238493.0 / 1068277825.0,
  41. 181606767.0 / 758867731.0,
  42. 561292985.0 / 797845732.0,
  43. -1041891430.0 / 1371343529.0,
  44. 760417239.0 / 1151165299.0,
  45. 118820643.0 / 751138087.0,
  46. -528747749.0 / 2220607170.0,
  47. 1.0 / 4.0
  48. };
  49. static const double A[] = {
  50. 13451932.0 / 455176623.0,
  51. 0.0,
  52. 0.0,
  53. 0.0,
  54. 0.0,
  55. -808719846.0 / 976000145.0,
  56. 1757004468.0 / 5645159321.0,
  57. 656045339.0 / 265891186.0,
  58. -3867574721.0 / 1518517206.0,
  59. 465885868.0 / 322736535.0,
  60. 53011238.0 / 667516719.0,
  61. 2.0 / 45.0
  62. };
  63. static const double ah[] = {
  64. 1.0 / 18.0,
  65. 1.0 / 12.0,
  66. 1.0 / 8.0,
  67. 5.0 / 16.0,
  68. 3.0 / 8.0,
  69. 59.0 / 400.0,
  70. 93.0 / 200.0,
  71. 5490023248.0 / 9719169821.0,
  72. 13.0 / 20.0,
  73. 1201146811.0 / 1299019798.0
  74. };
  75. static const double b21 = 1.0 / 18.0;
  76. static const double b3[] = { 1.0 / 48.0, 1.0 / 16.0 };
  77. static const double b4[] = { 1.0 / 32.0, 0.0, 3.0 / 32.0 };
  78. static const double b5[] = { 5.0 / 16.0, 0.0, -75.0 / 64.0, 75.0 / 64.0 };
  79. static const double b6[] = { 3.0 / 80.0, 0.0, 0.0, 3.0 / 16.0, 3.0 / 20.0 };
  80. static const double b7[] = {
  81. 29443841.0 / 614563906.0,
  82. 0.0,
  83. 0.0,
  84. 77736538.0 / 692538347.0,
  85. -28693883.0 / 1125000000.0,
  86. 23124283.0 / 1800000000.0
  87. };
  88. static const double b8[] = {
  89. 16016141.0 / 946692911.0,
  90. 0.0,
  91. 0.0,
  92. 61564180.0 / 158732637.0,
  93. 22789713.0 / 633445777.0,
  94. 545815736.0 / 2771057229.0,
  95. -180193667.0 / 1043307555.0
  96. };
  97. static const double b9[] = {
  98. 39632708.0 / 573591083.0,
  99. 0.0,
  100. 0.0,
  101. -433636366.0 / 683701615.0,
  102. -421739975.0 / 2616292301.0,
  103. 100302831.0 / 723423059.0,
  104. 790204164.0 / 839813087.0,
  105. 800635310.0 / 3783071287.0
  106. };
  107. static const double b10[] = {
  108. 246121993.0 / 1340847787.0,
  109. 0.0,
  110. 0.0,
  111. -37695042795.0 / 15268766246.0,
  112. -309121744.0 / 1061227803.0,
  113. -12992083.0 / 490766935.0,
  114. 6005943493.0 / 2108947869.0,
  115. 393006217.0 / 1396673457.0,
  116. 123872331.0 / 1001029789.0
  117. };
  118. static const double b11[] = {
  119. -1028468189.0 / 846180014.0,
  120. 0.0,
  121. 0.0,
  122. 8478235783.0 / 508512852.0,
  123. 1311729495.0 / 1432422823.0,
  124. -10304129995.0 / 1701304382.0,
  125. -48777925059.0 / 3047939560.0,
  126. 15336726248.0 / 1032824649.0,
  127. -45442868181.0 / 3398467696.0,
  128. 3065993473.0 / 597172653.0
  129. };
  130. static const double b12[] = {
  131. 185892177.0 / 718116043.0,
  132. 0.0,
  133. 0.0,
  134. -3185094517.0 / 667107341.0,
  135. -477755414.0 / 1098053517.0,
  136. -703635378.0 / 230739211.0,
  137. 5731566787.0 / 1027545527.0,
  138. 5232866602.0 / 850066563.0,
  139. -4093664535.0 / 808688257.0,
  140. 3962137247.0 / 1805957418.0,
  141. 65686358.0 / 487910083.0
  142. };
  143. static const double b13[] = {
  144. 403863854.0 / 491063109.0,
  145. 0.0,
  146. 0.0,
  147. -5068492393.0 / 434740067.0,
  148. -411421997.0 / 543043805.0,
  149. 652783627.0 / 914296604.0,
  150. 11173962825.0 / 925320556.0,
  151. -13158990841.0 / 6184727034.0,
  152. 3936647629.0 / 1978049680.0,
  153. -160528059.0 / 685178525.0,
  154. 248638103.0 / 1413531060.0,
  155. 0.0
  156. };
  157. typedef struct
  158. {
  159. double *k[13];
  160. double *ytmp;
  161. double *y0;
  162. }
  163. rk8pd_state_t;
  164. static void *
  165. rk8pd_alloc (size_t dim)
  166. {
  167. rk8pd_state_t *state = (rk8pd_state_t *) malloc (sizeof (rk8pd_state_t));
  168. int i, j;
  169. if (state == 0)
  170. {
  171. GSL_ERROR_NULL ("failed to allocate space for rk8pd_state", GSL_ENOMEM);
  172. }
  173. state->ytmp = (double *) malloc (dim * sizeof (double));
  174. if (state->ytmp == 0)
  175. {
  176. free (state);
  177. GSL_ERROR_NULL ("failed to allocate space for ytmp", GSL_ENOMEM);
  178. }
  179. state->y0 = (double *) malloc (dim * sizeof (double));
  180. if (state->y0 == 0)
  181. {
  182. free (state->ytmp);
  183. free (state);
  184. GSL_ERROR_NULL ("failed to allocate space for y0", GSL_ENOMEM);
  185. }
  186. for (i = 0; i < 13; i++)
  187. {
  188. state->k[i] = (double *) malloc (dim * sizeof (double));
  189. if (state->k[i] == 0)
  190. {
  191. for (j = 0; j < i; j++)
  192. {
  193. free (state->k[j]);
  194. }
  195. free (state->y0);
  196. free (state->ytmp);
  197. free (state);
  198. GSL_ERROR_NULL ("failed to allocate space for k's", GSL_ENOMEM);
  199. }
  200. }
  201. return state;
  202. }
  203. static int
  204. rk8pd_apply (void *vstate,
  205. size_t dim,
  206. double t,
  207. double h,
  208. double y[],
  209. double yerr[],
  210. const double dydt_in[],
  211. double dydt_out[], const gsl_odeiv_system * sys)
  212. {
  213. rk8pd_state_t *state = (rk8pd_state_t *) vstate;
  214. size_t i;
  215. double *const ytmp = state->ytmp;
  216. double *const y0 = state->y0;
  217. /* Note that k1 is stored in state->k[0] due to zero-based indexing */
  218. double *const k1 = state->k[0];
  219. double *const k2 = state->k[1];
  220. double *const k3 = state->k[2];
  221. double *const k4 = state->k[3];
  222. double *const k5 = state->k[4];
  223. double *const k6 = state->k[5];
  224. double *const k7 = state->k[6];
  225. double *const k8 = state->k[7];
  226. double *const k9 = state->k[8];
  227. double *const k10 = state->k[9];
  228. double *const k11 = state->k[10];
  229. double *const k12 = state->k[11];
  230. double *const k13 = state->k[12];
  231. DBL_MEMCPY (y0, y, dim);
  232. /* k1 step */
  233. if (dydt_in != NULL)
  234. {
  235. DBL_MEMCPY (k1, dydt_in, dim);
  236. }
  237. else
  238. {
  239. int s = GSL_ODEIV_FN_EVAL (sys, t, y, k1);
  240. if (s != GSL_SUCCESS)
  241. {
  242. return s;
  243. }
  244. }
  245. for (i = 0; i < dim; i++)
  246. ytmp[i] = y[i] + b21 * h * k1[i];
  247. /* k2 step */
  248. {
  249. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[0] * h, ytmp, k2);
  250. if (s != GSL_SUCCESS)
  251. {
  252. return s;
  253. }
  254. }
  255. for (i = 0; i < dim; i++)
  256. ytmp[i] = y[i] + h * (b3[0] * k1[i] + b3[1] * k2[i]);
  257. /* k3 step */
  258. {
  259. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[1] * h, ytmp, k3);
  260. if (s != GSL_SUCCESS)
  261. {
  262. return s;
  263. }
  264. }
  265. for (i = 0; i < dim; i++)
  266. ytmp[i] = y[i] + h * (b4[0] * k1[i] + b4[2] * k3[i]);
  267. /* k4 step */
  268. {
  269. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[2] * h, ytmp, k4);
  270. if (s != GSL_SUCCESS)
  271. {
  272. return s;
  273. }
  274. }
  275. for (i = 0; i < dim; i++)
  276. ytmp[i] = y[i] + h * (b5[0] * k1[i] + b5[2] * k3[i] + b5[3] * k4[i]);
  277. /* k5 step */
  278. {
  279. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[3] * h, ytmp, k5);
  280. if (s != GSL_SUCCESS)
  281. {
  282. return s;
  283. }
  284. }
  285. for (i = 0; i < dim; i++)
  286. ytmp[i] = y[i] + h * (b6[0] * k1[i] + b6[3] * k4[i] + b6[4] * k5[i]);
  287. /* k6 step */
  288. {
  289. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[4] * h, ytmp, k6);
  290. if (s != GSL_SUCCESS)
  291. {
  292. return s;
  293. }
  294. }
  295. for (i = 0; i < dim; i++)
  296. ytmp[i] =
  297. y[i] + h * (b7[0] * k1[i] + b7[3] * k4[i] + b7[4] * k5[i] +
  298. b7[5] * k6[i]);
  299. /* k7 step */
  300. {
  301. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[5] * h, ytmp, k7);
  302. if (s != GSL_SUCCESS)
  303. {
  304. return s;
  305. }
  306. }
  307. for (i = 0; i < dim; i++)
  308. ytmp[i] =
  309. y[i] + h * (b8[0] * k1[i] + b8[3] * k4[i] + b8[4] * k5[i] +
  310. b8[5] * k6[i] + b8[6] * k7[i]);
  311. /* k8 step */
  312. {
  313. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[6] * h, ytmp, k8);
  314. if (s != GSL_SUCCESS)
  315. {
  316. return s;
  317. }
  318. }
  319. for (i = 0; i < dim; i++)
  320. ytmp[i] =
  321. y[i] + h * (b9[0] * k1[i] + b9[3] * k4[i] + b9[4] * k5[i] +
  322. b9[5] * k6[i] + b9[6] * k7[i] + b9[7] * k8[i]);
  323. /* k9 step */
  324. {
  325. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[7] * h, ytmp, k9);
  326. if (s != GSL_SUCCESS)
  327. {
  328. return s;
  329. }
  330. }
  331. for (i = 0; i < dim; i++)
  332. ytmp[i] =
  333. y[i] + h * (b10[0] * k1[i] + b10[3] * k4[i] + b10[4] * k5[i] +
  334. b10[5] * k6[i] + b10[6] * k7[i] + b10[7] * k8[i] +
  335. b10[8] * k9[i]);
  336. /* k10 step */
  337. {
  338. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[8] * h, ytmp, k10);
  339. if (s != GSL_SUCCESS)
  340. {
  341. return s;
  342. }
  343. }
  344. for (i = 0; i < dim; i++)
  345. ytmp[i] =
  346. y[i] + h * (b11[0] * k1[i] + b11[3] * k4[i] + b11[4] * k5[i] +
  347. b11[5] * k6[i] + b11[6] * k7[i] + b11[7] * k8[i] +
  348. b11[8] * k9[i] + b11[9] * k10[i]);
  349. /* k11 step */
  350. {
  351. int s = GSL_ODEIV_FN_EVAL (sys, t + ah[9] * h, ytmp, k11);
  352. if (s != GSL_SUCCESS)
  353. {
  354. return s;
  355. }
  356. }
  357. for (i = 0; i < dim; i++)
  358. ytmp[i] =
  359. y[i] + h * (b12[0] * k1[i] + b12[3] * k4[i] + b12[4] * k5[i] +
  360. b12[5] * k6[i] + b12[6] * k7[i] + b12[7] * k8[i] +
  361. b12[8] * k9[i] + b12[9] * k10[i] + b12[10] * k11[i]);
  362. /* k12 step */
  363. {
  364. int s = GSL_ODEIV_FN_EVAL (sys, t + h, ytmp, k12);
  365. if (s != GSL_SUCCESS)
  366. {
  367. return s;
  368. }
  369. }
  370. for (i = 0; i < dim; i++)
  371. ytmp[i] =
  372. y[i] + h * (b13[0] * k1[i] + b13[3] * k4[i] + b13[4] * k5[i] +
  373. b13[5] * k6[i] + b13[6] * k7[i] + b13[7] * k8[i] +
  374. b13[8] * k9[i] + b13[9] * k10[i] + b13[10] * k11[i] +
  375. b13[11] * k12[i]);
  376. /* k13 step */
  377. {
  378. int s = GSL_ODEIV_FN_EVAL (sys, t + h, ytmp, k13);
  379. if (s != GSL_SUCCESS)
  380. {
  381. return s;
  382. }
  383. }
  384. /* final sum */
  385. for (i = 0; i < dim; i++)
  386. {
  387. const double ksum8 =
  388. Abar[0] * k1[i] + Abar[5] * k6[i] + Abar[6] * k7[i] +
  389. Abar[7] * k8[i] + Abar[8] * k9[i] + Abar[9] * k10[i] +
  390. Abar[10] * k11[i] + Abar[11] * k12[i] + Abar[12] * k13[i];
  391. y[i] += h * ksum8;
  392. }
  393. /* Evaluate dydt_out[]. */
  394. if (dydt_out != NULL)
  395. {
  396. int s = GSL_ODEIV_FN_EVAL (sys, t + h, y, dydt_out);
  397. if (s != GSL_SUCCESS)
  398. {
  399. /* Restore initial values */
  400. DBL_MEMCPY (y, y0, dim);
  401. return s;
  402. }
  403. }
  404. /* error estimate */
  405. for (i = 0; i < dim; i++)
  406. {
  407. const double ksum8 =
  408. Abar[0] * k1[i] + Abar[5] * k6[i] + Abar[6] * k7[i] +
  409. Abar[7] * k8[i] + Abar[8] * k9[i] + Abar[9] * k10[i] +
  410. Abar[10] * k11[i] + Abar[11] * k12[i] + Abar[12] * k13[i];
  411. const double ksum7 =
  412. A[0] * k1[i] + A[5] * k6[i] + A[6] * k7[i] + A[7] * k8[i] +
  413. A[8] * k9[i] + A[9] * k10[i] + A[10] * k11[i] + A[11] * k12[i];
  414. yerr[i] = h * (ksum7 - ksum8);
  415. }
  416. return GSL_SUCCESS;
  417. }
  418. static int
  419. rk8pd_reset (void *vstate, size_t dim)
  420. {
  421. rk8pd_state_t *state = (rk8pd_state_t *) vstate;
  422. int i;
  423. for (i = 0; i < 13; i++)
  424. {
  425. DBL_ZERO_MEMSET (state->k[i], dim);
  426. }
  427. DBL_ZERO_MEMSET (state->y0, dim);
  428. DBL_ZERO_MEMSET (state->ytmp, dim);
  429. return GSL_SUCCESS;
  430. }
  431. static unsigned int
  432. rk8pd_order (void *vstate)
  433. {
  434. rk8pd_state_t *state = (rk8pd_state_t *) vstate;
  435. state = 0; /* prevent warnings about unused parameters */
  436. return 8;
  437. }
  438. static void
  439. rk8pd_free (void *vstate)
  440. {
  441. rk8pd_state_t *state = (rk8pd_state_t *) vstate;
  442. int i;
  443. for (i = 0; i < 13; i++)
  444. {
  445. free (state->k[i]);
  446. }
  447. free (state->y0);
  448. free (state->ytmp);
  449. free (state);
  450. }
  451. static const gsl_odeiv_step_type rk8pd_type = { "rk8pd", /* name */
  452. 1, /* can use dydt_in */
  453. 1, /* gives exact dydt_out */
  454. &rk8pd_alloc,
  455. &rk8pd_apply,
  456. &rk8pd_reset,
  457. &rk8pd_order,
  458. &rk8pd_free
  459. };
  460. const gsl_odeiv_step_type *gsl_odeiv_step_rk8pd = &rk8pd_type;