Actual source code: cp.c
1: #define PETSCKSP_DLL
3: #include private/pcimpl.h
4: #include ../src/mat/impls/aij/seq/aij.h
6: /*
7: Private context (data structure) for the CP preconditioner.
8: */
9: typedef struct {
10: PetscInt n,m;
11: Vec work;
12: PetscScalar *d; /* sum of squares of each column */
13: PetscScalar *a; /* non-zeros by column */
14: PetscInt *i,*j; /* offsets of nonzeros by column, non-zero indices by column */
15: } PC_CP;
20: static PetscErrorCode PCSetUp_CP(PC pc)
21: {
22: PC_CP *cp = (PC_CP*)pc->data;
23: PetscInt i,j,*colcnt;
25: PetscTruth flg;
26: Mat_SeqAIJ *aij = (Mat_SeqAIJ*)pc->pmat->data;
29: PetscTypeCompare((PetscObject)pc->pmat,MATSEQAIJ,&flg);
30: if (!flg) SETERRQ(PETSC_ERR_SUP,"Currently only handles SeqAIJ matrices");
31:
32: MatGetLocalSize(pc->pmat,&cp->m,&cp->n);
33: if (cp->m != cp->n) SETERRQ(PETSC_ERR_SUP,"Currently only for square matrices");
34:
35: if (!cp->work) {MatGetVecs(pc->pmat,&cp->work,PETSC_NULL);}
36: if (!cp->d) {PetscMalloc(cp->n*sizeof(PetscScalar),&cp->d);}
37: if (cp->a && pc->flag != SAME_NONZERO_PATTERN) {
38: PetscFree3(cp->a,cp->i,cp->j);
39: cp->a = 0;
40: }
42: /* convert to column format */
43: if (!cp->a) {
44: PetscMalloc3(aij->nz,PetscScalar,&cp->a,cp->n+1,PetscInt,&cp->i,aij->nz,PetscInt,&cp->j);
45: }
46: PetscMalloc(cp->n*sizeof(PetscInt),&colcnt);
47: PetscMemzero(colcnt,cp->n*sizeof(PetscInt));
49: for (i=0; i<aij->nz; i++) {
50: colcnt[aij->j[i]]++;
51: }
52: cp->i[0] = 0;
53: for (i=0; i<cp->n; i++) {
54: cp->i[i+1] = cp->i[i] + colcnt[i];
55: }
56: PetscMemzero(colcnt,cp->n*sizeof(PetscInt));
57: for (i=0; i<cp->m; i++) { /* over rows */
58: for (j=aij->i[i]; j<aij->i[i+1]; j++) { /* over columns in row */
59: cp->j[cp->i[aij->j[j]]+colcnt[aij->j[j]]] = i;
60: cp->a[cp->i[aij->j[j]]+colcnt[aij->j[j]]++] = aij->a[j];
61: }
62: }
63: PetscFree(colcnt);
65: /* compute sum of squares of each column d[] */
66: for (i=0; i<cp->n; i++) { /* over columns */
67: cp->d[i] = 0.;
68: for (j=cp->i[i]; j<cp->i[i+1]; j++) { /* over rows in column */
69: cp->d[i] += cp->a[j]*cp->a[j];
70: }
71: cp->d[i] = 1.0/cp->d[i];
72: }
73: return(0);
74: }
75: /* -------------------------------------------------------------------------- */
78: static PetscErrorCode PCApply_CP(PC pc,Vec bb,Vec xx)
79: {
80: PC_CP *cp = (PC_CP*)pc->data;
82: PetscScalar *b,*x,xt;
83: PetscInt i,j;
86: VecCopy(bb,cp->work);
87: VecGetArray(cp->work,&b);
88: VecGetArray(xx,&x);
90: for (i=0; i<cp->n; i++) { /* over columns */
91: xt = 0.;
92: for (j=cp->i[i]; j<cp->i[i+1]; j++) { /* over rows in column */
93: xt += cp->a[j]*b[cp->j[j]];
94: }
95: xt *= cp->d[i];
96: x[i] = xt;
97: for (j=cp->i[i]; j<cp->i[i+1]; j++) { /* over rows in column updating b*/
98: b[cp->j[j]] -= xt*cp->a[j];
99: }
100: }
101: for (i=cp->n-1; i>-1; i--) { /* over columns */
102: xt = 0.;
103: for (j=cp->i[i]; j<cp->i[i+1]; j++) { /* over rows in column */
104: xt += cp->a[j]*b[cp->j[j]];
105: }
106: xt *= cp->d[i];
107: x[i] = xt;
108: for (j=cp->i[i]; j<cp->i[i+1]; j++) { /* over rows in column updating b*/
109: b[cp->j[j]] -= xt*cp->a[j];
110: }
111: }
113: VecRestoreArray(cp->work,&b);
114: VecRestoreArray(xx,&x);
115: return(0);
116: }
117: /* -------------------------------------------------------------------------- */
120: static PetscErrorCode PCDestroy_CP(PC pc)
121: {
122: PC_CP *cp = (PC_CP*)pc->data;
126: PetscFree(cp->d);
127: if (cp->work) {VecDestroy(cp->work);}
128: PetscFree3(cp->a,cp->i,cp->j);
129: PetscFree(cp);
130: return(0);
131: }
135: static PetscErrorCode PCSetFromOptions_CP(PC pc)
136: {
138: return(0);
139: }
142: /*MC
143: PCCP - a "column-projection" preconditioner
145: This is a terrible preconditioner and is not recommended, ever!
147: Loops over the entries of x computing dx_i to
148: $
149: $ min || b - A(x + dx_i e_i ||_2
150: $ dx_i
151: $
152: $ That is, it changes a single entry of x to minimize the new residual.
153: $ Let A_i represent the ith column of A, then the minimization can be written as
154: $
155: $ min || r - (dx_i) A e_i ||_2
156: $ dx_i
157: $ or min || r - (dx_i) A_i ||_2
158: $ dx_i
159: $
160: $ take the derivative with respect to dx_i to obtain
161: $ dx_i = (A_i^T A_i)^(-1) A_i^T r
162: $
163: $ This algorithm can be thought of as Gauss-Seidel on the normal equations
165: Notes: This proceedure can also be done with block columns or any groups of columns
166: but this is not coded.
168: These "projections" can be done simultaneously for all columns (similar to Jacobi)
169: or sequentially (similar to Gauss-Seidel/SOR). This is only coded for SOR type.
171: This is related to, but not the same as "row projection" methods.
173: This is currently coded only for SeqAIJ matrices in sequential (SOR) form.
174:
175: Level: intermediate
177: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PCJACOBI, PCSOR
179: M*/
184: PetscErrorCode PCCreate_CP(PC pc)
185: {
186: PC_CP *cp;
190: PetscNewLog(pc,PC_CP,&cp);
191: pc->data = (void*)cp;
193: pc->ops->apply = PCApply_CP;
194: pc->ops->applytranspose = PCApply_CP;
195: pc->ops->setup = PCSetUp_CP;
196: pc->ops->destroy = PCDestroy_CP;
197: pc->ops->setfromoptions = PCSetFromOptions_CP;
198: pc->ops->view = 0;
199: pc->ops->applyrichardson = 0;
200: return(0);
201: }