|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 00002 /***************************************************************************** 00003 * 00004 * MODULE: Grass PDE Numerical Library 00005 * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006 00006 * soerengebbert <at> gmx <dot> de 00007 * 00008 * PURPOSE: direkt linear equation system solvers 00009 * part of the gpde library 00010 * 00011 * COPYRIGHT: (C) 2007 by the GRASS Development Team 00012 * 00013 * This program is free software under the GNU General Public 00014 * License (>=v2). Read the file COPYING that comes with GRASS 00015 * for details. 00016 * 00017 *****************************************************************************/ 00018 00019 #include <math.h> 00020 #include <unistd.h> 00021 #include <stdio.h> 00022 #include <string.h> 00023 #include "grass/gis.h" 00024 #include "grass/glocale.h" 00025 #include "grass/gmath.h" 00026 00027 #define TINY 1.0e-20 00028 #define COMP_PIVOT 100 00029 00043 int G_math_solver_gauss(double **A, double *x, double *b, int rows) 00044 { 00045 G_message(_("Starting direct gauss elimination solver")); 00046 00047 G_math_gauss_elimination(A, b, rows); 00048 G_math_backward_solving(A, x, b, rows); 00049 00050 return 1; 00051 } 00052 00067 int G_math_solver_lu(double **A, double *x, double *b, int rows) 00068 { 00069 int i; 00070 00071 double *c, *tmpv; 00072 00073 G_message(_("Starting direct lu decomposition solver")); 00074 00075 tmpv = G_alloc_vector(rows); 00076 c = G_alloc_vector(rows); 00077 00078 G_math_lu_decomposition(A, b, rows); 00079 00080 #pragma omp parallel 00081 { 00082 00083 #pragma omp for schedule (static) private(i) 00084 for (i = 0; i < rows; i++) { 00085 tmpv[i] = A[i][i]; 00086 A[i][i] = 1; 00087 } 00088 00089 #pragma omp single 00090 { 00091 G_math_forward_solving(A, b, b, rows); 00092 } 00093 00094 #pragma omp for schedule (static) private(i) 00095 for (i = 0; i < rows; i++) { 00096 A[i][i] = tmpv[i]; 00097 } 00098 00099 #pragma omp single 00100 { 00101 G_math_backward_solving(A, x, b, rows); 00102 } 00103 } 00104 00105 G_free(c); 00106 G_free(tmpv); 00107 00108 00109 return 1; 00110 } 00111 00126 int G_math_solver_cholesky(double **A, double *x, double *b, int bandwith, 00127 int rows) 00128 { 00129 00130 G_message(_("Starting cholesky decomposition solver")); 00131 00132 if (G_math_cholesky_decomposition(A, rows, bandwith) != 1) { 00133 G_warning(_("Unable to solve the linear equation system")); 00134 return -2; 00135 } 00136 00137 G_math_forward_solving(A, b, b, rows); 00138 G_math_backward_solving(A, x, b, rows); 00139 00140 return 1; 00141 } 00142 00155 void G_math_gauss_elimination(double **A, double *b, int rows) 00156 { 00157 int i, j, k; 00158 00159 double tmpval = 0.0; 00160 00161 /*compute the pivot -- commented out, because its meaningless 00162 to compute it only nth times. */ 00163 /*G_math_pivot_create(A, b, rows, 0); */ 00164 00165 for (k = 0; k < rows - 1; k++) { 00166 #pragma omp parallel for schedule (static) private(i, j, tmpval) shared(k, A, b, rows) 00167 for (i = k + 1; i < rows; i++) { 00168 tmpval = A[i][k] / A[k][k]; 00169 b[i] = b[i] - tmpval * b[k]; 00170 for (j = k + 1; j < rows; j++) { 00171 A[i][j] = A[i][j] - tmpval * A[k][j]; 00172 } 00173 } 00174 } 00175 00176 return; 00177 } 00178 00192 void G_math_lu_decomposition(double **A, double *b, int rows) 00193 { 00194 00195 int i, j, k; 00196 00197 /*compute the pivot -- commented out, because its meaningless 00198 to compute it only nth times. */ 00199 /*G_math_pivot_create(A, b, rows, 0); */ 00200 00201 for (k = 0; k < rows - 1; k++) { 00202 #pragma omp parallel for schedule (static) private(i, j) shared(k, A, rows) 00203 for (i = k + 1; i < rows; i++) { 00204 A[i][k] = A[i][k] / A[k][k]; 00205 for (j = k + 1; j < rows; j++) { 00206 A[i][j] = A[i][j] - A[i][k] * A[k][j]; 00207 } 00208 } 00209 } 00210 00211 return; 00212 } 00213 00227 int G_math_cholesky_decomposition(double **A, int rows, int bandwith) 00228 { 00229 00230 int i = 0, j = 0, k = 0; 00231 00232 double sum_1 = 0.0; 00233 00234 double sum_2 = 0.0; 00235 00236 int colsize; 00237 00238 if (bandwith <= 0) 00239 bandwith = rows; 00240 00241 colsize = bandwith; 00242 00243 for (k = 0; k < rows; k++) { 00244 #pragma omp parallel for schedule (static) private(i, j, sum_2) shared(A, k) reduction(+:sum_1) 00245 for (j = 0; j < k; j++) { 00246 sum_1 += A[k][j] * A[k][j]; 00247 } 00248 00249 if (0 > (A[k][k] - sum_1)) { 00250 G_warning("Matrix is not positive definite. break."); 00251 return -1; 00252 } 00253 A[k][k] = sqrt(A[k][k] - sum_1); 00254 sum_1 = 0.0; 00255 00256 if ((k + bandwith) > rows) { 00257 colsize = rows; 00258 } 00259 else { 00260 colsize = k + bandwith; 00261 } 00262 00263 #pragma omp parallel for schedule (static) private(i, j, sum_2) shared(A, k, sum_1, colsize) 00264 00265 for (i = k + 1; i < colsize; i++) { 00266 sum_2 = 0.0; 00267 for (j = 0; j < k; j++) { 00268 sum_2 += A[i][j] * A[k][j]; 00269 } 00270 A[i][k] = (A[i][k] - sum_2) / A[k][k]; 00271 } 00272 00273 } 00274 /*we need to copy the lower triangle matrix to the upper trianle */ 00275 #pragma omp parallel for schedule (static) private(i, k) shared(A, rows) 00276 for (k = 0; k < rows; k++) { 00277 for (i = k + 1; i < rows; i++) { 00278 A[k][i] = A[i][k]; 00279 } 00280 } 00281 00282 00283 return 1; 00284 } 00285 00296 void G_math_backward_solving(double **A, double *x, double *b, int rows) 00297 { 00298 int i, j; 00299 00300 for (i = rows - 1; i >= 0; i--) { 00301 for (j = i + 1; j < rows; j++) { 00302 b[i] = b[i] - A[i][j] * x[j]; 00303 } 00304 x[i] = (b[i]) / A[i][i]; 00305 } 00306 00307 return; 00308 } 00309 00320 void G_math_forward_solving(double **A, double *x, double *b, int rows) 00321 { 00322 int i, j; 00323 00324 double tmpval = 0.0; 00325 00326 for (i = 0; i < rows; i++) { 00327 tmpval = 0; 00328 for (j = 0; j < i; j++) { 00329 tmpval += A[i][j] * x[j]; 00330 } 00331 x[i] = (b[i] - tmpval) / A[i][i]; 00332 } 00333 00334 return; 00335 } 00336 00337 00357 int G_math_pivot_create(double **A, double *b, int rows, int start) 00358 { 00359 int num = 0; /*number of changed rows */ 00360 00361 int i, j, k; 00362 00363 double max; 00364 00365 int number = 0; 00366 00367 double tmpval = 0.0, s = 0.0; 00368 00369 double *link = NULL; 00370 00371 link = G_alloc_vector(rows); 00372 00373 G_debug(2, "G_math_pivot_create: swap rows if needed"); 00374 for (i = start; i < rows; i++) { 00375 s = 0.0; 00376 for (k = i + 1; k < rows; k++) { 00377 s += fabs(A[i][k]); 00378 } 00379 max = fabs(A[i][i]) / s; 00380 number = i; 00381 for (j = i + 1; j < rows; j++) { 00382 s = 0.0; 00383 for (k = j; k < rows; k++) { 00384 s += fabs(A[j][k]); 00385 } 00386 /*search for the pivot element */ 00387 if (max < fabs(A[j][i]) / s) { 00388 max = fabs(A[j][i] / s); 00389 number = j; 00390 } 00391 } 00392 if (max == 0) { 00393 max = TINY; 00394 G_warning("Matrix is singular"); 00395 } 00396 /*if an pivot element was found, swap the les entries */ 00397 if (number != i) { 00398 00399 G_debug(4, "swap row %i with row %i", i, number); 00400 00401 if (b != NULL) { 00402 tmpval = b[number]; 00403 b[number] = b[i]; 00404 b[i] = tmpval; 00405 } 00406 G_math_d_copy(A[number], link, rows); 00407 G_math_d_copy(A[i], A[number], rows); 00408 G_math_d_copy(link, A[i], rows); 00409 num++; 00410 } 00411 } 00412 00413 G_free_vector(link); 00414 00415 return num; 00416 }