solvers_direct_cholesky_band.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <grass/gis.h>
  5. #include <grass/gmath.h>
  6. #include <grass/glocale.h>
  7. /**
  8. * \brief Cholesky decomposition of a symmetric band matrix
  9. *
  10. * \param A (double**) the input symmetric band matrix
  11. * \param T (double**) the resulting lower tringular symmetric band matrix
  12. * \param rows (int) number of rows
  13. * \param bandwidth (int) the bandwidth of the symmetric band matrix
  14. *
  15. * */
  16. void G_math_cholesky_sband_decomposition(double **A, double **T, int rows, int bandwidth)
  17. {
  18. int i, j, k, end;
  19. double sum;
  20. G_debug(2, "G_math_cholesky_sband_decomposition(): n=%d bandwidth=%d", rows, bandwidth);
  21. for (i = 0; i < rows; i++) {
  22. G_percent(i, rows, 9);
  23. /* For j = 0 */
  24. sum = A[i][0];
  25. end = ((bandwidth - 0) < (i + 1) ? (bandwidth - 0) : (i + 1));
  26. for (k = 1; k < end; k++)
  27. sum -= T[i - k][k] * T[i - k][0 + k];
  28. if (sum <= 0.0)
  29. G_fatal_error(_("Decomposition failed at row %i and col %i"), i, 0);
  30. T[i][0] = sqrt(sum);
  31. #pragma omp parallel for schedule (static) private(j, k, end, sum) shared(A, T, i, bandwidth)
  32. for (j = 1; j < bandwidth; j++) {
  33. sum = A[i][j];
  34. end = ((bandwidth - j) < (i + 1) ? (bandwidth - j) : (i + 1));
  35. for (k = 1; k < end; k++)
  36. sum -= T[i - k][k] * T[i - k][j + k];
  37. T[i][j] = sum / T[i][0];
  38. }
  39. }
  40. G_percent(i, rows, 2);
  41. return;
  42. }
  43. /**
  44. * \brief Cholesky symmetric band matrix solver for linear equation systems of type Ax = b
  45. *
  46. * \param A (double**) the input symmetric band matrix
  47. * \param x (double*) the resulting vector, result is written in here
  48. * \param b (double*) the right hand side of Ax = b
  49. * \param rows (int) number of rows
  50. * \param bandwidth (int) the bandwidth of the symmetric band matrix
  51. *
  52. * */
  53. void G_math_solver_cholesky_sband(double **A, double *x, double *b, int rows, int bandwidth)
  54. {
  55. double **T;
  56. T = G_alloc_matrix(rows, bandwidth);
  57. G_math_cholesky_sband_decomposition(A, T, rows, bandwidth); /* T computation */
  58. G_math_cholesky_sband_substitution(T, x, b, rows, bandwidth);
  59. G_free_matrix(T);
  60. return;
  61. }
  62. /**
  63. * \brief Forward and backward substitution of a lower tringular symmetric band matrix of A from system Ax = b
  64. *
  65. * \param T (double**) the lower triangle symmetric band matrix
  66. * \param x (double*) the resulting vector
  67. * \param b (double*) the right hand side of Ax = b
  68. * \param rows (int) number of rows
  69. * \param bandwidth (int) the bandwidth of the symmetric band matrix
  70. *
  71. * */
  72. void G_math_cholesky_sband_substitution(double **T, double *x, double *b, int rows, int bandwidth)
  73. {
  74. int i, j, start, end;
  75. /* Forward substitution */
  76. x[0] = b[0] / T[0][0];
  77. for (i = 1; i < rows; i++) {
  78. x[i] = b[i];
  79. /* start = 0 or i - bandwidth + 1 */
  80. start = ((i - bandwidth + 1) < 0 ? 0 : (i - bandwidth + 1));
  81. /* end = i */
  82. for (j = start; j < i; j++)
  83. x[i] -= T[j][i - j] * x[j];
  84. x[i] = x[i] / T[i][0];
  85. }
  86. /* Backward substitution */
  87. x[rows - 1] = x[rows - 1] / T[rows - 1][0];
  88. for (i = rows - 2; i >= 0; i--) {
  89. /* start = i + 1 */
  90. /* end = rows or bandwidth + i */
  91. end = (rows < (bandwidth + i) ? rows : (bandwidth + i));
  92. for (j = i + 1; j < end; j++)
  93. x[i] -= T[i][j - i] * x[j];
  94. x[i] = x[i] / T[i][0];
  95. }
  96. return;
  97. }
  98. /*--------------------------------------------------------------------------------------*/
  99. /* Tcholetsky matrix invertion */
  100. void G_math_cholesky_sband_invert(double **A, double *invAdiag, int rows, int bandwidth)
  101. {
  102. double **T = NULL;
  103. double *vect = NULL;
  104. int i, j, k, start;
  105. double sum;
  106. T = G_alloc_matrix(rows, bandwidth);
  107. vect = G_alloc_vector(rows);
  108. /* T computation */
  109. G_math_cholesky_sband_decomposition(A, T, rows, bandwidth);
  110. /* T Diagonal invertion */
  111. for (i = 0; i < rows; i++) {
  112. T[i][0] = 1.0 / T[i][0];
  113. }
  114. /* A Diagonal invertion */
  115. for (i = 0; i < rows; i++) {
  116. vect[0] = T[i][0];
  117. invAdiag[i] = vect[0] * vect[0];
  118. for (j = i + 1; j < rows; j++) {
  119. sum = 0.0;
  120. /* start = i or j - bandwidth + 1 */
  121. start = ((j - bandwidth + 1) < i ? i : (j - bandwidth + 1));
  122. /* end = j */
  123. for (k = start; k < j; k++) {
  124. sum -= vect[k - i] * T[k][j - k];
  125. }
  126. vect[j - i] = sum * T[j][0];
  127. invAdiag[i] += vect[j - i] * vect[j - i];
  128. }
  129. }
  130. G_free_matrix(T);
  131. G_free_vector(vect);
  132. return;
  133. }
  134. /*--------------------------------------------------------------------------------------*/
  135. /* Tcholetsky matrix solution and invertion */
  136. void G_math_solver_cholesky_sband_invert(double **A, double *x, double *b, double *invAdiag,
  137. int rows, int bandwidth)
  138. {
  139. double **T = NULL;
  140. double *vect = NULL;
  141. int i, j, k, start;
  142. double sum;
  143. T = G_alloc_matrix(rows, bandwidth);
  144. vect = G_alloc_vector(rows);
  145. /* T computation */
  146. G_math_cholesky_sband_decomposition(A, T, rows, bandwidth);
  147. G_math_cholesky_sband_substitution(T, x, b, rows, bandwidth);
  148. /* T Diagonal invertion */
  149. for (i = 0; i < rows; i++) {
  150. T[i][0] = 1.0 / T[i][0];
  151. }
  152. /* A Diagonal invertion */
  153. for (i = 0; i < rows; i++) {
  154. vect[0] = T[i][0];
  155. invAdiag[i] = vect[0] * vect[0];
  156. for (j = i + 1; j < rows; j++) {
  157. sum = 0.0;
  158. /* start = i or j - bandwidth + 1 */
  159. start = ((j - bandwidth + 1) < i ? i : (j - bandwidth + 1));
  160. /* end = j */
  161. for (k = start; k < j; k++) {
  162. sum -= vect[k - i] * T[k][j - k];
  163. }
  164. vect[j - i] = sum * T[j][0];
  165. invAdiag[i] += vect[j - i] * vect[j - i];
  166. }
  167. }
  168. G_free_matrix(T);
  169. G_free_vector(vect);
  170. return;
  171. }