Actual source code: axpy.c

  1: #define PETSCMAT_DLL

 3:  #include src/mat/matimpl.h

  7: /*@
  8:    MatAXPY - Computes Y = a*X + Y.

 10:    Collective on Mat

 12:    Input Parameters:
 13: +  a - the scalar multiplier
 14: .  X - the first matrix
 15: .  Y - the second matrix
 16: -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN

 18:    Contributed by: Matthew Knepley

 20:    Notes:
 21:      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN

 23:    Level: intermediate

 25: .keywords: matrix, add

 27: .seealso: MatAYPX()
 28:  @*/
 29: PetscErrorCode PETSCMAT_DLLEXPORT MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str)
 30: {
 32:   PetscInt       m1,m2,n1,n2;


 38:   MatGetSize(X,&m1,&n1);
 39:   MatGetSize(Y,&m2,&n2);
 40:   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %D %D %D %D",m1,m2,n1,n2);

 42:   if (Y->ops->axpy) {
 43:     (*Y->ops->axpy)(Y,a,X,str);
 44:   } else {
 45:     MatAXPY_Basic(Y,a,X,str);
 46:   }
 47:   return(0);
 48: }


 53: PetscErrorCode MatAXPY_Basic(Mat Y,PetscScalar a,Mat X,MatStructure str)
 54: {
 55:   PetscInt          i,start,end,j,ncols,m,n;
 56:   PetscErrorCode    ierr;
 57:   const PetscInt    *row;
 58:   PetscScalar       *val;
 59:   const PetscScalar *vals;

 62:   MatGetSize(X,&m,&n);
 63:   MatGetOwnershipRange(X,&start,&end);
 64:   if (a == 1.0) {
 65:     for (i = start; i < end; i++) {
 66:       MatGetRow(X,i,&ncols,&row,&vals);
 67:       MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);
 68:       MatRestoreRow(X,i,&ncols,&row,&vals);
 69:     }
 70:   } else {
 71:     PetscMalloc((n+1)*sizeof(PetscScalar),&val);
 72:     for (i=start; i<end; i++) {
 73:       MatGetRow(X,i,&ncols,&row,&vals);
 74:       for (j=0; j<ncols; j++) {
 75:         val[j] = a*vals[j];
 76:       }
 77:       MatSetValues(Y,1,&i,ncols,row,val,ADD_VALUES);
 78:       MatRestoreRow(X,i,&ncols,&row,&vals);
 79:     }
 80:     PetscFree(val);
 81:   }
 82:   MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
 83:   MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
 84:   return(0);
 85: }

 89: /*@
 90:    MatShift - Computes Y =  Y + a I, where a is a PetscScalar and I is the identity matrix.

 92:    Collective on Mat

 94:    Input Parameters:
 95: +  Y - the matrices
 96: -  a - the PetscScalar 

 98:    Level: intermediate

100: .keywords: matrix, add, shift

102: .seealso: MatDiagonalSet()
103:  @*/
104: PetscErrorCode PETSCMAT_DLLEXPORT MatShift(Mat Y,PetscScalar a)
105: {
107:   PetscInt       i,start,end;

111:   if (!Y->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
112:   if (Y->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
113:   MatPreallocated(Y);

115:   if (Y->ops->shift) {
116:     (*Y->ops->shift)(Y,a);
117:   } else {
118:     PetscScalar alpha = a;
119:     MatGetOwnershipRange(Y,&start,&end);
120:     for (i=start; i<end; i++) {
121:       MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);
122:     }
123:     MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
124:     MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
125:   }
126:   return(0);
127: }

131: /*@
132:    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
133:    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
134:    INSERT_VALUES.

136:    Input Parameters:
137: +  Y - the input matrix
138: .  D - the diagonal matrix, represented as a vector
139: -  i - INSERT_VALUES or ADD_VALUES

141:    Collective on Mat and Vec

143:    Level: intermediate

145: .keywords: matrix, add, shift, diagonal

147: .seealso: MatShift()
148: @*/
149: PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet(Mat Y,Vec D,InsertMode is)
150: {
152:   PetscInt       i,start,end;

157:   if (Y->ops->diagonalset) {
158:     (*Y->ops->diagonalset)(Y,D,is);
159:   } else {
160:     PetscInt    vstart,vend;
161:     PetscScalar *v;
162:     VecGetOwnershipRange(D,&vstart,&vend);
163:     MatGetOwnershipRange(Y,&start,&end);
164:     if (vstart != start || vend != end) {
165:       SETERRQ4(PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %D %D vec %D %D mat",vstart,vend,start,end);
166:     }
167:     VecGetArray(D,&v);
168:     for (i=start; i<end; i++) {
169:       MatSetValues(Y,1,&i,1,&i,v+i-start,is);
170:     }
171:     VecRestoreArray(D,&v);
172:     MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
173:     MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
174:   }
175:   return(0);
176: }

180: /*@
181:    MatAYPX - Computes Y = X + a*Y.

183:    Collective on Mat

185:    Input Parameters:
186: +  X,Y - the matrices
187: -  a - the PetscScalar multiplier

189:    Contributed by: Matthew Knepley

191:    Notes:
192:    This routine currently uses the MatAXPY() implementation.

194:    This is slow, if you need it fast send email to petsc-maint@mcs.anl.gov

196:    Level: intermediate

198: .keywords: matrix, add

200: .seealso: MatAXPY()
201:  @*/
202: PetscErrorCode PETSCMAT_DLLEXPORT MatAYPX(Mat Y,PetscScalar a,Mat X)
203: {
204:   PetscScalar    one = 1.0;
206:   PetscInt       mX,mY,nX,nY;


212:   MatGetSize(X,&mX,&nX);
213:   MatGetSize(X,&mY,&nY);
214:   if (mX != mY || nX != nY) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrices: %D %D first %D %D second",mX,mY,nX,nY);

216:   MatScale(Y,a);
217:   MatAXPY(Y,one,X,DIFFERENT_NONZERO_PATTERN);
218:   return(0);
219: }

223: /*@
224:     MatComputeExplicitOperator - Computes the explicit matrix

226:     Collective on Mat

228:     Input Parameter:
229: .   inmat - the matrix

231:     Output Parameter:
232: .   mat - the explict preconditioned operator

234:     Notes:
235:     This computation is done by applying the operators to columns of the 
236:     identity matrix.

238:     Currently, this routine uses a dense matrix format when 1 processor
239:     is used and a sparse format otherwise.  This routine is costly in general,
240:     and is recommended for use only with relatively small systems.

242:     Level: advanced
243:    
244: .keywords: Mat, compute, explicit, operator

246: @*/
247: PetscErrorCode PETSCMAT_DLLEXPORT MatComputeExplicitOperator(Mat inmat,Mat *mat)
248: {
249:   Vec            in,out;
251:   PetscInt       i,M,m,*rows,start,end;
252:   MPI_Comm       comm;
253:   PetscScalar    *array,zero = 0.0,one = 1.0;
254:   PetscMPIInt    size;


260:   comm = inmat->comm;
261:   MPI_Comm_size(comm,&size);

263:   MatGetLocalSize(inmat,&m,0);
264:   MatGetSize(inmat,&M,0);
265:   VecCreateMPI(comm,m,M,&in);
266:   VecDuplicate(in,&out);
267:   VecGetOwnershipRange(in,&start,&end);
268:   PetscMalloc((m+1)*sizeof(PetscInt),&rows);
269:   for (i=0; i<m; i++) {rows[i] = start + i;}

271:   MatCreate(comm,mat);
272:   MatSetSizes(*mat,m,m,M,M);
273:   if (size == 1) {
274:     MatSetType(*mat,MATSEQDENSE);
275:     MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
276:   } else {
277:     MatSetType(*mat,MATMPIAIJ);
278:     MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);
279:   }

281:   for (i=0; i<M; i++) {

283:     VecSet(in,zero);
284:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
285:     VecAssemblyBegin(in);
286:     VecAssemblyEnd(in);

288:     MatMult(inmat,in,out);
289: 
290:     VecGetArray(out,&array);
291:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
292:     VecRestoreArray(out,&array);

294:   }
295:   PetscFree(rows);
296:   VecDestroy(out);
297:   VecDestroy(in);
298:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
299:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
300:   return(0);
301: }

303: /* Get the map xtoy which is used by MatAXPY() in the case of SUBSET_NONZERO_PATTERN */
306: PetscErrorCode MatAXPYGetxtoy_Private(PetscInt m,PetscInt *xi,PetscInt *xj,PetscInt *xgarray, PetscInt *yi,PetscInt *yj,PetscInt *ygarray, PetscInt **xtoy)
307: {
309:   PetscInt       row,i,nz,xcol,ycol,jx,jy,*x2y;

312:   PetscMalloc(xi[m]*sizeof(PetscInt),&x2y);
313:   i = 0;
314:   for (row=0; row<m; row++){
315:     nz = xi[1] - xi[0];
316:     jy = 0;
317:     for (jx=0; jx<nz; jx++,jy++){
318:       if (xgarray && ygarray){
319:         xcol = xgarray[xj[*xi + jx]];
320:         ycol = ygarray[yj[*yi + jy]];
321:       } else {
322:         xcol = xj[*xi + jx];
323:         ycol = yj[*yi + jy];  /* col index for y */
324:       }
325:       while ( ycol < xcol ) {
326:         jy++;
327:         if (ygarray){
328:           ycol = ygarray[yj[*yi + jy]];
329:         } else {
330:           ycol = yj[*yi + jy];
331:         }
332:       }
333:       if (xcol != ycol) SETERRQ2(PETSC_ERR_ARG_WRONG,"X matrix entry (%D,%D) is not in Y matrix",row,ycol);
334:       x2y[i++] = *yi + jy;
335:     }
336:     xi++; yi++;
337:   }
338:   *xtoy = x2y;
339:   return(0);
340: }