openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
Rosenbrock.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: LicenseRef-APL-1.1
3 
4 #define NO_INCLUDE_ROSENBROCK_CU
5 
6 /* ----------------------------------------------------------------------------
7 Rosenbrock-Wolfbrandt Integration Coefficients, culled from:
8 http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19960015529_1996034599.pdf
9 ---------------------------------------------------------------------------- */
10 #include <string.h>
11 
12 #include "Rosenbrock.h"
13 
14 #if defined HAS_ROCM_MODEL
15 #include <hip/hip_runtime.h>
16 #endif
17 
18 namespace limpet {
19 
20 #ifdef __cplusplus
21 extern "C"
22 {
23 #endif // ifdef __cplusplus
24 
25 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
26 __device__
27 #endif
28 void rbCalcKi ( float **K, float **, float *X, int* ludI,
29  void (*calcDX)(float*, float*, void*),
30  void *params, float h, int N, int i );
31 
32 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
33 __device__
34 #endif
35 void rbSolver ( float **, float *, float *, int N );
36 
37 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
38 __device__
39 #endif
40 void fludcmp0 ( float **, int n, int *indx, float *);
41 
42 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
43 __device__
44 #endif
45 
46 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
47 __device__
48 #endif
49 void flubksb0 ( float **, int n, int *indx, float *);
50 
51 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
52 __device__
53 #endif
54 void fludcmp ( float **, int, int *, float *);
55 
56 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
57 __device__
58 #endif
59 void flubksb ( float **, int, int *, float * );
60 
61 
83 #if defined __CUDA__ || defined __HIP__
84 __device__
85 #endif
86 void rbStepX ( float *X, void (*calcDX)(float*, float*, void*),
87  void (*calcJ)(float**, float*, void*, int ),
88  void *params, float h, int N )
89 {
90  float kbuf[RS_MAX_N*RS_ORDER];
91  float *k[RS_ORDER];
92  float abuf[RS_MAX_N*RS_MAX_N];
93  float *a[RS_MAX_N];
94 
95  //const float A_rs[RS_ORDER] = { 0., 0.5, 0.5, 1. };
96  //const float B_rs[RS_ORDER] = { 0.25, 0.25, 0.25, 0.25 };
97  const float Chi[RS_ORDER] = { 14/3., 20/3., 4/3., 2/3. };
98 
99  if (N > RS_MAX_N) {
100 #if !defined __CUDA__ && !defined __HIP__
101  printf( "Increase limit for number of equations: currently %d\n", RS_MAX_N);
102 #elif defined __CUDA__
103  printf( "Error: Increase limit for number of equations (RS_MAX_N macro)\n");
104 #endif
105  return;
106  }
107 
108  memset(kbuf, 0, sizeof(kbuf));
109  memset(abuf, 0, sizeof(abuf));
110 
111  for( int i = 0; i < RS_ORDER || i < N; i++ ) {
112  if( i < RS_ORDER ) k[i] = &(kbuf[i*N]);
113  if( i < N ) a[i] = &(abuf[i*N]);
114  }
115  calcJ(a, X, params, N);
116 
117  // a = 4i - hj;
118  for( int i = 0; i < N; i++ )
119  for( int j = 0; j < N; j++ )
120  a[i][j] = ((i == j) ? 4 : 0) - h * a[i][j];
121 
122  int ludI[RS_MAX_N];
123  float ludD;
124  fludcmp0( a, N, ludI, &ludD );
125 
126  for( int ki = 0; ki < RS_ORDER; ki++)
127  rbCalcKi ( k, a, X, ludI, calcDX, params, h, N, ki );
128 
129  for( int Ki = 0; Ki < RS_ORDER; Ki++)
130  for( int row = 0; row < N; row++ )
131  X[row] += h * Chi[Ki] * k[Ki][row];
132 
133 }
134 
135 
152 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
153 __device__
154 #endif
155 void rbCalcKi ( float **K, float **A, float *X, int* ludI,
156  void (*calcDX)(float*, float*, void*),
157  void *params, float h, int N, int i )
158 {
159 
160  float xx[RS_MAX_N];
161  const float Alpha[RS_ORDER][RS_ORDER] = {
162  { 0, 0, 0, 0 },
163  { 2, 0, 0, 0 },
164  { 2, 2, 0, 0 },
165  { 6, 10, 4, 0 } };
166  const float Beta[RS_ORDER][RS_ORDER] = {
167  { 0, 0, 0, 0 },
168  { -4, 0, 0, 0 },
169  { -6, -10, 0, 0 },
170  { -4, -12, 0, 0 } };
171 
172  memcpy( xx, X, N * sizeof(float));
173 
174  for( int j = 0; j < i; j++ ) {
175  for( int row = 0; row < N; row++ ) {
176  xx[row] += h * Alpha[i][j] * K[j][row];
177  K[i][row] += Beta[i][j] * K[j][row];
178  }
179  }
180 
181  float DXi[RS_MAX_N];
182  calcDX( DXi, xx, params );
183 
184  for( int row = 0; row < N; row++ ) K[i][row] += DXi[row];
185 
186  // rbSolver( &A[0][0], &K[RM(N,i,0)], bb, N );
187  flubksb0( A, N, ludI, K[i] );
188  return;
189 }
190 
204 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
205 __device__
206 #endif
207 void rbSolver( float **A, float *x, float *b, int N ) {
208  // Purpose: solve the system Ax = b by Gaussian elimination
209 
210  // Step #1: convert the system to upper-diagonal form
211  for( int i = 1; i < N; i++ ) {
212  for( int j = 0; j < i; j++ ) {
213  // Set A[i][j] to zero.
214  float K = -A[i][j] / A[j][j];
215  for( int k = j; k < N; k++ ) A[i][k] += K * A[j][k];
216  b[i] += K * b[j];
217  }
218  }
219 
220  // Step #2: solve for x by back-substitution
221  for(int i = N - 1; i >= 0; i--) {
222  x[i] = b[i];
223  for(int j = i + 1; j < N; j++) x[i] -= A[i][j] * x[j];
224  x[i] /= A[i][i];
225  }
226 }
227 
228 
240 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
241 __device__
242 #endif
243 void fludcmp0( float **a, int n,int *indx, float *d)/* matrices start at 0 */
244 {
245  float *ptr[RS_MAX_N+1];
246  int i;
247 
248  for( i=0; i<n; i++ )
249  ptr[i+1] = a[i]-1;
250  fludcmp( ptr, n, indx-1, d );
251 
252  for(i=0; i<n; i++)
253  a[i] = ptr[i+1] + 1;
254 }
255 
267 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
268 __device__
269 #endif
270 void flubksb0( float **a, int n, int *indx, float *b)
271 {
272  float *ptr[RS_MAX_N+1];
273  int i;
274 
275  for( i=0; i<n; i++ )
276  ptr[i+1] = a[i]-1;
277 
278  flubksb( ptr, n, indx-1, b-1 );
279 }
280 
281 #define TINY 1.0e-20;
282 
283 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
284 __device__
285 #endif
286 void fludcmp( float **a, int n,int *indx, float *d)
287 {
288  int i,j;
289  int imax = 0,k;
290  float big,dum,temp;
291  float sum;
292  float *dumpoint, vv[RS_MAX_N+1];
293 
294 
295  *d=1.0;
296  i = 1;
297  do {
298  big=0.0;
299  for (j=1;j<=n;j++)
300  if ((temp=fabs(a[i][j])) > big) big=temp;
301  if (big == 0.0) {
302  #ifndef __HIP__
303  printf("Singular matrix in routine LUDCMP");
304  #endif
305  //exit(1);
306  //
307  }
308  vv[i]=1.0/big;
309  } while ( ++i <= n );
310 
311  j = 1;
312  do {
313  if( j > 1 ) {
314  i = 1;
315  do {
316  sum=a[i][j];
317  if ( i != 1 ) {
318  k = 1;
319  do {
320  sum -= a[i][k]*a[k][j];
321  } while ( ++k < i );
322  }
323  a[i][j]=sum;
324  } while ( ++i < j );
325  }
326  big=0.0;
327  i = j;
328  do {
329  sum=a[i][j];
330  if ( j > 1 ) {
331  k =1 ;
332  do {
333  sum -= a[i][k]*a[k][j];
334  } while( ++k < j );
335  }
336  a[i][j]=sum;
337  if ( (dum=vv[i]*fabs(sum)) >= big) {
338  big=dum;
339  imax=i;
340  }
341  } while( ++i <= n );
342  if (j != imax) { /* exchange rows */
343  dumpoint=a[imax];
344  a[imax]=a[j];
345  a[j]=dumpoint;
346  *d = -(*d);
347  vv[imax]=vv[j];
348  }
349  indx[j]=imax;
350  if (a[j][j] == 0.0) a[j][j]=TINY;
351  if (j != n) {
352  dum=1.0/(a[j][j]);
353  for (i=j+1;i<=n;i++) a[i][j] *= dum;
354  }
355  } while( ++j <= n );
356 }
357 
358 #undef TINY
359 
360 #if defined MLIR_CODEGEN && (defined __CUDA__ || defined __HIP__)
361 __device__
362 #endif
363 void flubksb( float **a, int n, int *indx, float *b )
364 {
365  int i,ii=0,ip;
366  int j;
367  float sum;
368 
369  for (i=1;i<=n;i++) {
370  ip=indx[i];
371  sum=b[ip];
372  b[ip]=b[i];
373  if (ii)
374  for (j=ii;j<=i-1;j++)
375  sum -= a[i][j]*b[j];
376  else if (sum)
377  ii=i;
378  b[i]=sum;
379  }
380  for (i=n;i>=1;i--) {
381  sum=b[i];
382  for (j=i+1;j<=n;j++)
383  sum -= a[i][j]*b[j];
384  b[i]=sum/a[i][i];
385  }
386 }
387 
388 #ifdef __cplusplus
389 }
390 #endif // ifdef __cplusplus
391 
392 #if defined MLIR_CODEGEN && !defined __CUDA__ && !defined __HIP__
393 
410 template<size_t vector_size>
411 void rbCalcKi(float **K, float **A, float *X, int* ludI,
412  void (*calcDX)(float*, float*, void*),
413  void *params, float h, int N, int i)
414 {
415 
416  float xx[RS_MAX_N * vector_size];
417  const float Alpha[RS_ORDER][RS_ORDER] = {
418  { 0, 0, 0, 0 },
419  { 2, 0, 0, 0 },
420  { 2, 2, 0, 0 },
421  { 6, 10, 4, 0 } };
422  const float Beta[RS_ORDER][RS_ORDER] = {
423  { 0, 0, 0, 0 },
424  { -4, 0, 0, 0 },
425  { -6, -10, 0, 0 },
426  { -4, -12, 0, 0 } };
427 
428  memcpy(xx, X, N*vector_size*sizeof(float));
429 
430  for (int v = 0; v < vector_size; ++v) {
431  for( int j = 0; j < i; j++ ) {
432  for( int row = 0; row < N; row++ ) {
433  xx[v*N + row] += h * Alpha[i][j] * K[v*RS_ORDER + j][row];
434  K[v*RS_ORDER + i][row] += Beta[i][j] * K[v*RS_ORDER + j][row];
435  }
436  }
437  }
438 
439  float DXi[RS_MAX_N * vector_size];
440  calcDX( DXi, xx, params );
441  for (int v = 0; v < vector_size; ++v)
442  for( int row = 0; row < N; row++ )
443  K[v*RS_ORDER + i][row] += DXi[v*N + row];
444 
445  for (int v = 0; v < vector_size; ++v)
446  flubksb0(&A[v*N], N, ludI+v*N, K[v*RS_ORDER + i]);
447 }
448 
470 template<size_t vector_size>
471 void rbStepX ( float *X, void (*calcDX)(float*, float*, void*),
472  void (*calcJ)(float*, float*, void*, int ),
473  void *params, float h, int N )
474 {
475  float kbuf[RS_MAX_N*RS_ORDER*vector_size];
476  float *k[RS_ORDER*vector_size];
477  float abuf[RS_MAX_N*RS_MAX_N*vector_size];
478  float *a[RS_MAX_N*vector_size];
479 
480  const float Chi[RS_ORDER] = { 14/3., 20/3., 4/3., 2/3. };
481 
482  if(N>RS_MAX_N) {
483  printf( "Increase limit for number of equations: currently %d\n", RS_MAX_N );
484  return;
485  }
486 
487  memset(kbuf, 0, sizeof(kbuf));
488  memset(abuf, 0, sizeof(abuf));
489 
490  int K_ORDER = N > RS_ORDER ? N : RS_ORDER;
491  for (int i = 0; i < vector_size; ++i) {
492  for( int j = 0; j < RS_ORDER || j < N; j++ ) {
493  if( j < RS_ORDER ) k[i*RS_ORDER + j] = &(kbuf[i*K_ORDER*K_ORDER + j*K_ORDER]);
494  if( j < N ) a[i*N + j] = &(abuf[i*N*N + j*N]);
495  }
496  }
497  calcJ(abuf, X, params, N);
498 
499  for (int i = 0; i < vector_size; ++i)
500  for( int j = 0; j < N; j++ )
501  for( int k = 0; k < N; k++ )
502  a[i*N + j][k] = ((j == k) ? 4 : 0) - h * a[i*N + j][k];
503 
504  int ludI[RS_MAX_N * vector_size];
505  for (int i = 0; i < vector_size; ++i) {
506  float ludD;
507  fludcmp0( &a[i*N], N, ludI + i * N, &ludD );
508  }
509 
510  for( int ki = 0; ki < RS_ORDER; ki++)
511  rbCalcKi<vector_size>( k, a, X, ludI, calcDX, params, h, N, ki);
512 
513  for (int i = 0; i < vector_size; ++i)
514  for( int Ki = 0; Ki < RS_ORDER; Ki++)
515  for( int row = 0; row < N; row++ )
516  X[i*N + row] += h * Chi[Ki] * k[i * RS_ORDER + Ki][row];
517 }
518 
519 #ifdef __cplusplus
520 extern "C"
521 {
522 #endif // ifdef __cplusplus
523 
524 void rbStepX_2 ( float *X, void (*calcDX)(float*, float*, void*),
525  void (*calcJ)(float*, float*, void*, int ),
526  void *params, float h, int N )
527 {
528  rbStepX<2>(X, calcDX, calcJ, params, h, N);
529 }
530 
531 void rbStepX_4 ( float *X, void (*calcDX)(float*, float*, void*),
532  void (*calcJ)(float*, float*, void*, int ),
533  void *params, float h, int N )
534 {
535  rbStepX<4>(X, calcDX, calcJ, params, h, N);
536 }
537 
538 void rbStepX_8 ( float *X, void (*calcDX)(float*, float*, void*),
539  void (*calcJ)(float*, float*, void*, int ),
540  void *params, float h, int N )
541 {
542  rbStepX<8>(X, calcDX, calcJ, params, h, N);
543 }
544 
545 void rbStepX_16 ( float *X, void (*calcDX)(float*, float*, void*),
546  void (*calcJ)(float*, float*, void*, int ),
547  void *params, float h, int N )
548 {
549  rbStepX<16>(X, calcDX, calcJ, params, h, N);
550 }
551 
552 void rbStepX_32 ( float *X, void (*calcDX)(float*, float*, void*),
553  void (*calcJ)(float*, float*, void*, int ),
554  void *params, float h, int N )
555 {
556  rbStepX<32>(X, calcDX, calcJ, params, h, N);
557 }
558 
559 #ifdef __cplusplus
560 }
561 #endif // ifdef __cplusplus
562 
563 #endif
564 
565 } // namespace limpet
#define TINY
Definition: Rosenbrock.cc:281
#define RS_MAX_N
Definition: Rosenbrock.h:15
#define RS_ORDER
Definition: Rosenbrock.h:14
T sum(const vector< T > &vec)
Compute sum of a vector's entries.
Definition: SF_vector.h:325
@ X
Definition: kdpart.hpp:49
void rbSolver(float **, float *, float *, int N)
Definition: Rosenbrock.cc:207
void fludcmp(float **, int, int *, float *)
Definition: Rosenbrock.cc:286
void flubksb(float **, int, int *, float *)
Definition: Rosenbrock.cc:363
void rbStepX(float *X, void(*calcDX)(float *, float *, void *), void(*calcJ)(float **, float *, void *, int), void *params, float h, int N)
Definition: Rosenbrock.cc:86
void flubksb0(float **, int n, int *indx, float *)
Definition: Rosenbrock.cc:270
void rbCalcKi(float **K, float **, float *X, int *ludI, void(*calcDX)(float *, float *, void *), void *params, float h, int N, int i)
Definition: Rosenbrock.cc:155
void fludcmp0(float **, int n, int *indx, float *)
Definition: Rosenbrock.cc:243