| | 1 | = Cg.c = |
| | 2 | {{{#!C |
| | 3 | /* |
| | 4 | Large Scale Computing |
| | 5 | |
| | 6 | solve Ax=b |
| | 7 | Conjugate Gradient Method |
| | 8 | General Sparse Matrix A |
| | 9 | |
| | 10 | solve_cg solve Ax=b with CG method |
| | 11 | this returns the number of iterations, or negative if failed. |
| | 12 | |
| | 13 | Note: A must be symmetric and positive-defined matrix |
| | 14 | */ |
| | 15 | #include<stdio.h> |
| | 16 | |
| | 17 | int solve_cg(int dim, /* dimension */ |
| | 18 | int nnz, /* # of non-zeros in the matrix */ |
| | 19 | double *nzval, /* array of nonzero values */ |
| | 20 | int *colidx, /* array of column indices of the nonzeros */ |
| | 21 | int *rowptr, /* the first column of nonzero in each row */ |
| | 22 | /* rowptr[j] stores the location of nzval[] and colidx[], */ |
| | 23 | /* which starts row j. This has dim+1 entry that is nnz */ |
| | 24 | double *x, /* solition */ |
| | 25 | double *b, /* right hand side */ |
| | 26 | double tol); /* tolerance */ |
| | 27 | }}} |
| | 28 | {{{#!C |
| | 29 | /* |
| | 30 | Large Scale Computing |
| | 31 | |
| | 32 | solve Ax=b |
| | 33 | Conjugate Gradient Method |
| | 34 | General Sparse Matrix A |
| | 35 | |
| | 36 | Note: A must be symmetric and positive-defined matrix |
| | 37 | */ |
| | 38 | #include<stdio.h> |
| | 39 | #include<stdlib.h> |
| | 40 | #include<math.h> |
| | 41 | |
| | 42 | int solve_cg(int dim, /* dimension */ |
| | 43 | int nnz, /* # of non-zeros in the matrix */ |
| | 44 | double *nzval, /* array of nonzero values */ |
| | 45 | int *colidx, /* array of column indices of the nonzeros */ |
| | 46 | int *rowptr, /* the first column of nonzero in each row */ |
| | 47 | double *x, /* solition */ |
| | 48 | double *b, /* right hand side */ |
| | 49 | double tol){ /* tolerance */ |
| | 50 | double *r; |
| | 51 | double *p; |
| | 52 | double *Ap; |
| | 53 | double rr,pAp,rr1,alpha,beta; |
| | 54 | int i,j,count; |
| | 55 | |
| | 56 | /* Allocate Working Spaces */ |
| | 57 | r = (double *)calloc(dim, sizeof(double)); |
| | 58 | p = (double *)calloc(dim, sizeof(double)); |
| | 59 | Ap = (double *)calloc(dim, sizeof(double)); |
| | 60 | if ((r == NULL) || (p == NULL) || (Ap == NULL)){ |
| | 61 | printf("memory allocation failed\n"); |
| | 62 | return -1; |
| | 63 | } |
| | 64 | |
| | 65 | /* compute r0 */ |
| | 66 | for (i = 0 ; i < dim ; i++){ |
| | 67 | r[i] = b[i]; |
| | 68 | for (j = rowptr[i] ; j < rowptr[i+1] ; j++){ |
| | 69 | r[i] -= nzval[j] * x[colidx[j]]; |
| | 70 | } |
| | 71 | } |
| | 72 | |
| | 73 | rr = 0.0; |
| | 74 | for (i = 0 ; i < dim ; i++){ |
| | 75 | p[i] = r[i]; /* p = r */ |
| | 76 | rr += r[i] * r[i]; /* rr = r.r */ |
| | 77 | } |
| | 78 | |
| | 79 | /* cg iteration */ |
| | 80 | count = 0; |
| | 81 | while(rr > tol){ |
| | 82 | // Ap = A*p |
| | 83 | for (i = 0 ; i < dim ; i++){ |
| | 84 | Ap[i] = 0.0; |
| | 85 | for (j = rowptr[i] ; j < rowptr[i+1] ; j++){ |
| | 86 | Ap[i] += nzval[j] * p[colidx[j]]; |
| | 87 | } |
| | 88 | } |
| | 89 | |
| | 90 | // alpha = r.r / p.Ap |
| | 91 | pAp = 0.0; |
| | 92 | for (i = 0 ; i < dim ; i++){ |
| | 93 | pAp += p[i] * Ap[i]; |
| | 94 | } |
| | 95 | alpha = rr / pAp; |
| | 96 | |
| | 97 | //Beta |
| | 98 | rr1 = 0.0; |
| | 99 | for (i = 0 ; i < dim ; i++){ |
| | 100 | x[i] += alpha * p[i]; |
| | 101 | r[i] -= alpha * Ap[i]; |
| | 102 | rr1 += r[i] * r[i]; |
| | 103 | } |
| | 104 | |
| | 105 | beta = rr1 / rr; |
| | 106 | for (i = 0 ; i < dim ; i++){ |
| | 107 | p[i] = r[i] + beta * p[i]; |
| | 108 | } |
| | 109 | |
| | 110 | rr = rr1; |
| | 111 | count++; |
| | 112 | } |
| | 113 | |
| | 114 | /* Deallocate Working Spaces */ |
| | 115 | free(r); |
| | 116 | free(p); |
| | 117 | free(Ap); |
| | 118 | |
| | 119 | return count; |
| | 120 | } |
| | 121 | }}} |