rka.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /* This file is part of the GNU plotutils package. */
  2. /*
  3. * Copyright (C) 1982-1994, Nicholas B. Tufillaro. All rights reserved.
  4. *
  5. * GNU enhancements Copyright (C) 1996, 1997, 2005, 2008, Free Software
  6. * Foundation, Inc.
  7. */
  8. /*
  9. * Fifth-Order Runge-Kutta-Fehlberg with adaptive step size
  10. *
  11. */
  12. #include "sys-defines.h"
  13. #include "ode.h"
  14. #include "extern.h"
  15. #include "num.h"
  16. #define T_LT_TSTOP (tstep>0 ? t<tstop : t>tstop)
  17. void
  18. rka (void)
  19. {
  20. bool gdval = true; /* good value to print ? */
  21. int overtime = 1;
  22. double prevstep = 0.0;
  23. double t;
  24. for (it = 0, t = tstart; T_LT_TSTOP || overtime--; )
  25. {
  26. symtab->sy_value = symtab->sy_val[0] = t;
  27. field();
  28. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  29. {
  30. fsp->sy_val[0] = fsp->sy_value;
  31. fsp->sy_pri[0] = fsp->sy_prime;
  32. }
  33. if (gdval)
  34. printq(); /* output */
  35. if (tstep * (t+tstep-tstop) > 0)
  36. tstep = tstop - t;
  37. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  38. {
  39. fsp->sy_k[0] = tstep * fsp->sy_prime;
  40. fsp->sy_value = fsp->sy_val[0]
  41. + C20 * fsp->sy_k[0];
  42. }
  43. symtab->sy_value = t + C2t * tstep;
  44. field();
  45. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  46. {
  47. fsp->sy_k[1] = tstep * fsp->sy_prime;
  48. fsp->sy_value = fsp->sy_val[0]
  49. + (C30 * fsp->sy_k[0]
  50. + C31 * fsp->sy_k[1]);
  51. }
  52. symtab->sy_value = t + C3t * tstep;
  53. field();
  54. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  55. {
  56. fsp->sy_k[2] = tstep * fsp->sy_prime;
  57. fsp->sy_value = fsp->sy_val[0]
  58. + (C40 * fsp->sy_k[0]
  59. + C41 * fsp->sy_k[1]
  60. + C42 * fsp->sy_k[2]);
  61. }
  62. symtab->sy_value = t + C4t * tstep;
  63. field();
  64. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  65. {
  66. fsp->sy_k[3] = tstep * fsp->sy_prime;
  67. fsp->sy_value = fsp->sy_val[0]
  68. + (C50 * fsp->sy_k[0]
  69. + C51 * fsp->sy_k[1]
  70. + C52 * fsp->sy_k[2]
  71. + C53 * fsp->sy_k[3]);
  72. }
  73. symtab->sy_value = t + tstep;
  74. field();
  75. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  76. {
  77. fsp->sy_k[4] = tstep * fsp->sy_prime;
  78. fsp->sy_value = fsp->sy_val[0]
  79. + (C60 * fsp->sy_k[0]
  80. + C61 * fsp->sy_k[1]
  81. + C62 * fsp->sy_k[2]
  82. + C63 * fsp->sy_k[3]
  83. + C64 * fsp->sy_k[4]);
  84. }
  85. symtab->sy_value = t + C6t * tstep;
  86. field();
  87. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  88. fsp->sy_k[5] = tstep * fsp->sy_prime;
  89. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  90. {
  91. fsp->sy_predi = fsp->sy_val[0]
  92. + (A0 * fsp->sy_k[0]
  93. + A2 * fsp->sy_k[2]
  94. + A3 * fsp->sy_k[3]
  95. + A4 * fsp->sy_k[4]);
  96. fsp->sy_value = fsp->sy_val[0]
  97. + (B0 * fsp->sy_k[0]
  98. + B2 * fsp->sy_k[2]
  99. + B3 * fsp->sy_k[3]
  100. + B4 * fsp->sy_k[4]
  101. + B5 * fsp->sy_k[5]);
  102. if (fsp->sy_value != 0.0)
  103. fsp->sy_sserr = fabs(1.0 - fsp->sy_predi / fsp->sy_value);
  104. fsp->sy_aberr = fabs(fsp->sy_value - fsp->sy_predi);
  105. }
  106. if (!conflag && T_LT_TSTOP)
  107. {
  108. maxerr();
  109. if (hierror())
  110. {
  111. tstep *= HALF;
  112. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  113. fsp->sy_value = fsp->sy_val[0];
  114. gdval = false;
  115. continue;
  116. }
  117. else
  118. if (lowerror() && prevstep != tstep)
  119. {
  120. prevstep = tstep; /* prevent infinite loops */
  121. tstep *= TWO;
  122. for (fsp = dqueue; fsp != NULL; fsp = fsp->sy_link)
  123. fsp->sy_value = fsp->sy_val[0];
  124. gdval = false;
  125. continue;
  126. }
  127. }
  128. gdval = true;
  129. prevstep = 0.0;
  130. ++it;
  131. t += tstep; /* the roundoff error is gross */
  132. }
  133. }