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