solver.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. // #ifdef __cplusplus
  2. // extern "C" {
  3. // #endif
  4. //========================================================================================================================================================================================================200
  5. // DESCRIPTION
  6. //========================================================================================================================================================================================================200
  7. //======================================================================================================================================================150
  8. // UPDATE
  9. //======================================================================================================================================================150
  10. // Summary of changes by Lukasz G. Szafaryn:
  11. // 1) The original code was obtained from: Mathematics Source Library (http://mymathlib.webtrellis.net/index.html)
  12. // 2) This solver and particular solving algorithm used with it (embedded_fehlberg_7_8) were adapted to work with a set of equations, not just one like in original version.
  13. // 3) In order for solver to provide deterministic number of steps (needed for particular amount of memore previousely allocated for results), every next step is incremented by 1 time unit (h_init).
  14. // 4) Function assumes that time interval starts at 0 (xmin) and ends at integer value (xmax) specified by the uses as a parameter on command line.
  15. // 5) The appropriate amount of memory is previousely allocated for that range (y).
  16. // 5) This setup in 3) - 5) allows solver to adjust the step ony from current time instance to current time instance + 0.9. The next time instance is current time instance + 1;
  17. // 6) Solver also takes parameters (params) that it then passes to the equations.
  18. // 7) The original solver cannot handle cases when equations return NAN and INF values due to discontinuities and /0. That is why equations provided by user need to make sure that no NAN and INF are returned.
  19. // Last update: 15 DEC 09
  20. //======================================================================================================================================================150
  21. // DESCRIPTION
  22. //======================================================================================================================================================150
  23. // int solver( fp (*f)(fp, fp), fp y[], //
  24. // fp x, fp h, fp xmax, fp *h_next, fp tolerance ) //
  25. // //
  26. // Description: //
  27. // This function solves the differential equation y'=f(x,y) with the //
  28. // initial condition y(x) = y[0]. The value at xmax is returned in y[1]. //
  29. // The function returns 0 if successful or -1 if it fails. //
  30. // //
  31. // Arguments: //
  32. // fp *f Pointer to the function which returns the slope at (x,y) of //
  33. // integral curve of the differential equation y' = f(x,y) //
  34. // which passes through the point (x0,y0) corresponding to the //
  35. // initial condition y(x0) = y0. //
  36. // fp y[] On input y[0] is the initial value of y at x, on output //
  37. // y[1] is the solution at xmax. //
  38. // fp x The initial value of x. //
  39. // fp h Initial step size. //
  40. // fp xmax The endpoint of x. //
  41. // fp *h_next A pointer to the estimated step size for successive //
  42. // calls to solver. //
  43. // fp tolerance The tolerance of y(xmax), i.e. a solution is sought //
  44. // so that the relative error < tolerance. //
  45. // //
  46. // Return Values: //
  47. // 0 The solution of y' = f(x,y) from x to xmax is stored y[1] and //
  48. // h_next has the value to the next size to try. //
  49. // -1 The solution of y' = f(x,y) from x to xmax failed. //
  50. // -2 Failed because either xmax < x or the step size h <= 0. //
  51. // -3 Memory limit allocated for results was reached //
  52. //========================================================================================================================================================================================================200
  53. // DEFINE/INCLUDE
  54. //========================================================================================================================================================================================================200
  55. //======================================================================================================================================================150
  56. // COMMON
  57. //======================================================================================================================================================150
  58. #include "../common.h" // (in path provided here)
  59. //======================================================================================================================================================150
  60. // DEFINE
  61. //======================================================================================================================================================150
  62. #define max(x,y) ( (x) < (y) ? (y) : (x) )
  63. #define min(x,y) ( (x) < (y) ? (x) : (y) )
  64. #define ATTEMPTS 12
  65. #define MIN_SCALE_FACTOR 0.125
  66. #define MAX_SCALE_FACTOR 4.0
  67. //======================================================================================================================================================150
  68. // KERNEL
  69. //======================================================================================================================================================150
  70. #include "./embedded_fehlberg_7_8.c" // (in path provided here)
  71. //======================================================================================================================================================150
  72. // LIBRARIES
  73. //======================================================================================================================================================150
  74. #include <stdlib.h> // (in path known to compiler) needed by malloc, free
  75. #include <math.h> // (in path known to compiler) needed by pow, fabs
  76. //======================================================================================================================================================150
  77. // END
  78. //======================================================================================================================================================150
  79. //========================================================================================================================================================================================================200
  80. // FUNCTION
  81. //========================================================================================================================================================================================================200
  82. int
  83. solver( fp **y,
  84. fp *x,
  85. int xmax,
  86. fp *params,
  87. fp *com,
  88. cl_mem d_initvalu,
  89. cl_mem d_finavalu,
  90. cl_mem d_params,
  91. cl_mem d_com,
  92. cl_command_queue command_queue,
  93. cl_kernel kernel,
  94. long long *timecopyin,
  95. long long *timecopykernel,
  96. long long *timecopyout)
  97. {
  98. //========================================================================================================================
  99. // VARIABLES
  100. //========================================================================================================================
  101. // solver parameters
  102. fp err_exponent;
  103. int error;
  104. int outside;
  105. fp h;
  106. fp h_init;
  107. fp tolerance;
  108. int xmin;
  109. // memory
  110. fp scale_min;
  111. fp scale_fina;
  112. fp* err= (fp *) malloc(EQUATIONS* sizeof(fp));
  113. fp* scale= (fp *) malloc(EQUATIONS* sizeof(fp));
  114. fp* yy= (fp *) malloc(EQUATIONS* sizeof(fp));
  115. // counters
  116. int i, j, k;
  117. //========================================================================================================================
  118. // INITIAL SETUP
  119. //========================================================================================================================
  120. // solver parameters
  121. err_exponent = 1.0 / 7.0;
  122. h_init = 1;
  123. h = h_init;
  124. xmin = 0;
  125. tolerance = 10 / (fp)(xmax-xmin);
  126. // save value for initial time instance
  127. x[0] = 0;
  128. //========================================================================================================================
  129. // CHECKING
  130. //========================================================================================================================
  131. // Verify that the step size is positive and that the upper endpoint of integration is greater than the initial enpoint. //
  132. if (xmax < xmin || h <= 0.0){
  133. return -2;
  134. }
  135. // If the upper endpoint of the independent variable agrees with the initial value of the independent variable. Set the value of the dependent variable and return success. //
  136. if (xmax == xmin){
  137. return 0;
  138. }
  139. // Insure that the step size h is not larger than the length of the integration interval. //
  140. if (h > (xmax - xmin) ) {
  141. h = (fp)xmax - (fp)xmin;
  142. }
  143. //========================================================================================================================
  144. // SOLVING
  145. //========================================================================================================================
  146. printf("Time Steps: ");
  147. fflush(0);
  148. for(k=1; k<=xmax; k++) { // start after initial value
  149. x[k] = k-1;
  150. h = h_init;
  151. //==========================================================================================
  152. // REINITIALIZE VARIABLES
  153. //==========================================================================================
  154. scale_fina = 1.0;
  155. //==========================================================================================
  156. // MAKE ATTEMPTS TO MINIMIZE ERROR
  157. //==========================================================================================
  158. // make attempts to minimize error
  159. for (j = 0; j < ATTEMPTS; j++) {
  160. //============================================================
  161. // REINITIALIZE VARIABLES
  162. //============================================================
  163. error = 0;
  164. outside = 0;
  165. scale_min = MAX_SCALE_FACTOR;
  166. //============================================================
  167. // EVALUATE ALL EQUATIONS
  168. //============================================================
  169. embedded_fehlberg_7_8( x[k],
  170. h,
  171. y[k-1],
  172. y[k],
  173. err,
  174. params,
  175. com,
  176. d_initvalu,
  177. d_finavalu,
  178. d_params,
  179. d_com,
  180. command_queue,
  181. kernel,
  182. timecopyin,
  183. timecopykernel,
  184. timecopyout);
  185. //============================================================
  186. // IF THERE WAS NO ERROR FOR ANY OF EQUATIONS, SET SCALE AND LEAVE THE LOOP
  187. //============================================================
  188. for(i=0; i<EQUATIONS; i++){
  189. if(err[i] > 0){
  190. error = 1;
  191. }
  192. }
  193. if (error != 1) {
  194. scale_fina = MAX_SCALE_FACTOR;
  195. break;
  196. }
  197. //============================================================
  198. // FIGURE OUT SCALE AS THE MINIMUM OF COMPONENT SCALES
  199. //============================================================
  200. for(i=0; i<EQUATIONS; i++){
  201. if(y[k-1][i] == 0.0){
  202. yy[i] = tolerance;
  203. }
  204. else{
  205. yy[i] = fabs(y[k-1][i]);
  206. }
  207. scale[i] = 0.8 * pow( tolerance * yy[i] / err[i] , err_exponent );
  208. if(scale[i]<scale_min){
  209. scale_min = scale[i];
  210. }
  211. }
  212. scale_fina = min( max(scale_min,MIN_SCALE_FACTOR), MAX_SCALE_FACTOR);
  213. //============================================================
  214. // IF WITHIN TOLERANCE, FINISH ATTEMPTS...
  215. //============================================================
  216. for(i=0; i<EQUATIONS; i++){
  217. if ( err[i] > ( tolerance * yy[i] ) ){
  218. outside = 1;
  219. }
  220. }
  221. if (outside == 0){
  222. break;
  223. }
  224. //============================================================
  225. // ...OTHERWISE, ADJUST STEP FOR NEXT ATTEMPT
  226. //============================================================
  227. // scale next step in a default way
  228. h = h * scale_fina;
  229. // limit step to 0.9, because when it gets close to 1, it no longer makes sense, as 1 is already the next time instance (added to original algorithm)
  230. if (h >= 0.9) {
  231. h = 0.9;
  232. }
  233. // if instance+step exceeds range limit, limit to that range
  234. if ( x[k] + h > (fp)xmax ){
  235. h = (fp)xmax - x[k];
  236. }
  237. // if getting closer to range limit, decrease step
  238. else if ( x[k] + h + 0.5 * h > (fp)xmax ){
  239. h = 0.5 * h;
  240. }
  241. }
  242. //==========================================================================================
  243. // SAVE TIME INSTANCE THAT SOLVER ENDED UP USING
  244. //==========================================================================================
  245. x[k] = x[k] + h;
  246. //==========================================================================================
  247. // IF MAXIMUM NUMBER OF ATTEMPTS REACHED AND CANNOT GIVE SOLUTION, EXIT PROGRAM WITH ERROR
  248. //==========================================================================================
  249. if ( j >= ATTEMPTS ) {
  250. return -1;
  251. }
  252. printf("%d ", k);
  253. fflush(0);
  254. }
  255. printf("\n");
  256. fflush(0);
  257. //========================================================================================================================
  258. // FREE MEMORY
  259. //========================================================================================================================
  260. free(err);
  261. free(scale);
  262. free(yy);
  263. //========================================================================================================================
  264. // FINAL RETURN
  265. //========================================================================================================================
  266. return 0;
  267. //======================================================================================================================================================
  268. //======================================================================================================================================================
  269. // END OF SOLVER FUNCTION
  270. //======================================================================================================================================================
  271. //======================================================================================================================================================
  272. }
  273. //========================================================================================================================================================================================================200
  274. // END
  275. //========================================================================================================================================================================================================200
  276. // #ifdef __cplusplus
  277. // }
  278. // #endif