1 #define PETSCKSP_DLL 2 3 #include "private/pcimpl.h" /*I "petscpc.h" I*/ 4 #include "../src/mat/impls/aij/seq/aij.h" 5 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; 16 17 18 #undef __FUNCT__ 19 #define __FUNCT__ "PCSetUp_CP" 20 static PetscErrorCode PCSetUp_CP(PC pc) 21 { 22 PC_CP *cp = (PC_CP*)pc->data; 23 PetscInt i,j,*colcnt; 24 PetscErrorCode ierr; 25 PetscBool flg; 26 Mat_SeqAIJ *aij = (Mat_SeqAIJ*)pc->pmat->data; 27 28 PetscFunctionBegin; 29 ierr = PetscTypeCompare((PetscObject)pc->pmat,MATSEQAIJ,&flg);CHKERRQ(ierr); 30 if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_SUP,"Currently only handles SeqAIJ matrices"); 31 32 ierr = MatGetLocalSize(pc->pmat,&cp->m,&cp->n);CHKERRQ(ierr); 33 if (cp->m != cp->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently only for square matrices"); 34 35 if (!cp->work) {ierr = MatGetVecs(pc->pmat,&cp->work,PETSC_NULL);CHKERRQ(ierr);} 36 if (!cp->d) {ierr = PetscMalloc(cp->n*sizeof(PetscScalar),&cp->d);CHKERRQ(ierr);} 37 if (cp->a && pc->flag != SAME_NONZERO_PATTERN) { 38 ierr = PetscFree3(cp->a,cp->i,cp->j);CHKERRQ(ierr); 39 cp->a = 0; 40 } 41 42 /* convert to column format */ 43 if (!cp->a) { 44 ierr = PetscMalloc3(aij->nz,PetscScalar,&cp->a,cp->n+1,PetscInt,&cp->i,aij->nz,PetscInt,&cp->j);CHKERRQ(ierr); 45 } 46 ierr = PetscMalloc(cp->n*sizeof(PetscInt),&colcnt);CHKERRQ(ierr); 47 ierr = PetscMemzero(colcnt,cp->n*sizeof(PetscInt));CHKERRQ(ierr); 48 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 ierr = PetscMemzero(colcnt,cp->n*sizeof(PetscInt));CHKERRQ(ierr); 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 ierr = PetscFree(colcnt);CHKERRQ(ierr); 64 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 PetscFunctionReturn(0); 74 } 75 /* -------------------------------------------------------------------------- */ 76 #undef __FUNCT__ 77 #define __FUNCT__ "PCApply_CP" 78 static PetscErrorCode PCApply_CP(PC pc,Vec bb,Vec xx) 79 { 80 PC_CP *cp = (PC_CP*)pc->data; 81 PetscErrorCode ierr; 82 PetscScalar *b,*x,xt; 83 PetscInt i,j; 84 85 PetscFunctionBegin; 86 ierr = VecCopy(bb,cp->work);CHKERRQ(ierr); 87 ierr = VecGetArray(cp->work,&b);CHKERRQ(ierr); 88 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 89 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 } 112 113 ierr = VecRestoreArray(cp->work,&b);CHKERRQ(ierr); 114 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 115 PetscFunctionReturn(0); 116 } 117 /* -------------------------------------------------------------------------- */ 118 #undef __FUNCT__ 119 #define __FUNCT__ "PCReset_CP" 120 static PetscErrorCode PCReset_CP(PC pc) 121 { 122 PC_CP *cp = (PC_CP*)pc->data; 123 PetscErrorCode ierr; 124 125 PetscFunctionBegin; 126 ierr = PetscFree(cp->d);CHKERRQ(ierr); 127 if (cp->work) {ierr = VecDestroy(cp->work);CHKERRQ(ierr);} 128 ierr = PetscFree3(cp->a,cp->i,cp->j);CHKERRQ(ierr); 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PCDestroy_CP" 134 static PetscErrorCode PCDestroy_CP(PC pc) 135 { 136 PC_CP *cp = (PC_CP*)pc->data; 137 PetscErrorCode ierr; 138 139 PetscFunctionBegin; 140 ierr = PCReset_CP(pc);CHKERRQ(ierr); 141 ierr = PetscFree(cp->d);CHKERRQ(ierr); 142 ierr = PetscFree3(cp->a,cp->i,cp->j);CHKERRQ(ierr); 143 ierr = PetscFree(pc->data);CHKERRQ(ierr); 144 PetscFunctionReturn(0); 145 } 146 147 #undef __FUNCT__ 148 #define __FUNCT__ "PCSetFromOptions_CP" 149 static PetscErrorCode PCSetFromOptions_CP(PC pc) 150 { 151 PetscFunctionBegin; 152 PetscFunctionReturn(0); 153 } 154 155 156 /*MC 157 PCCP - a "column-projection" preconditioner 158 159 This is a terrible preconditioner and is not recommended, ever! 160 161 Loops over the entries of x computing dx_i to 162 $ 163 $ min || b - A(x + dx_i e_i ||_2 164 $ dx_i 165 $ 166 $ That is, it changes a single entry of x to minimize the new residual. 167 $ Let A_i represent the ith column of A, then the minimization can be written as 168 $ 169 $ min || r - (dx_i) A e_i ||_2 170 $ dx_i 171 $ or min || r - (dx_i) A_i ||_2 172 $ dx_i 173 $ 174 $ take the derivative with respect to dx_i to obtain 175 $ dx_i = (A_i^T A_i)^(-1) A_i^T r 176 $ 177 $ This algorithm can be thought of as Gauss-Seidel on the normal equations 178 179 Notes: This proceedure can also be done with block columns or any groups of columns 180 but this is not coded. 181 182 These "projections" can be done simultaneously for all columns (similar to Jacobi) 183 or sequentially (similar to Gauss-Seidel/SOR). This is only coded for SOR type. 184 185 This is related to, but not the same as "row projection" methods. 186 187 This is currently coded only for SeqAIJ matrices in sequential (SOR) form. 188 189 Level: intermediate 190 191 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PCJACOBI, PCSOR 192 193 M*/ 194 195 EXTERN_C_BEGIN 196 #undef __FUNCT__ 197 #define __FUNCT__ "PCCreate_CP" 198 PetscErrorCode PCCreate_CP(PC pc) 199 { 200 PC_CP *cp; 201 PetscErrorCode ierr; 202 203 PetscFunctionBegin; 204 ierr = PetscNewLog(pc,PC_CP,&cp);CHKERRQ(ierr); 205 pc->data = (void*)cp; 206 207 pc->ops->apply = PCApply_CP; 208 pc->ops->applytranspose = PCApply_CP; 209 pc->ops->setup = PCSetUp_CP; 210 pc->ops->reset = PCReset_CP; 211 pc->ops->destroy = PCDestroy_CP; 212 pc->ops->setfromoptions = PCSetFromOptions_CP; 213 pc->ops->view = 0; 214 pc->ops->applyrichardson = 0; 215 PetscFunctionReturn(0); 216 } 217 EXTERN_C_END 218 219 220