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: }