Actual source code: axpy.c

  2: #include <private/matimpl.h>  /*I   "petscmat.h"  I*/

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

  9:    Logically  Collective on Mat

 11:    Input Parameters:
 12: +  a - the scalar multiplier
 13: .  X - the first matrix
 14: .  Y - the second matrix
 15: -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN 
 16:          or SUBSET_NONZERO_PATTERN (nonzeros of X is a subset of Y's)

 18:    Level: intermediate

 20: .keywords: matrix, add

 22: .seealso: MatAYPX()
 23:  @*/
 24: PetscErrorCode  MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str)
 25: {
 27:   PetscInt       m1,m2,n1,n2;

 33:   MatGetSize(X,&m1,&n1);
 34:   MatGetSize(Y,&m2,&n2);
 35:   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %D %D %D %D",m1,m2,n1,n2);

 37:   PetscLogEventBegin(MAT_AXPY,Y,0,0,0);
 38:   if (Y->ops->axpy) {
 39:     (*Y->ops->axpy)(Y,a,X,str);
 40:   } else {
 41:     MatAXPY_Basic(Y,a,X,str);
 42:   }
 43:   PetscLogEventEnd(MAT_AXPY,Y,0,0,0);
 44:   return(0);
 45: }

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

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

 85: PetscErrorCode MatAXPY_BasicWithPreallocation(Mat B,Mat Y,PetscScalar a,Mat X,MatStructure str)
 86: {
 87:   PetscInt          i,start,end,j,ncols,m,n;
 88:   PetscErrorCode    ierr;
 89:   const PetscInt    *row;
 90:   PetscScalar       *val;
 91:   const PetscScalar *vals;

 94:   MatGetSize(X,&m,&n);
 95:   MatGetOwnershipRange(X,&start,&end);
 96:   if (a == 1.0) {
 97:     for (i = start; i < end; i++) {
 98:       MatGetRow(Y,i,&ncols,&row,&vals);
 99:       MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);
100:       MatRestoreRow(Y,i,&ncols,&row,&vals);

102:       MatGetRow(X,i,&ncols,&row,&vals);
103:       MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);
104:       MatRestoreRow(X,i,&ncols,&row,&vals);
105:     }
106:   } else {
107:     PetscMalloc((n+1)*sizeof(PetscScalar),&val);
108:     for (i=start; i<end; i++) {
109:       MatGetRow(Y,i,&ncols,&row,&vals);
110:       MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);
111:       MatRestoreRow(Y,i,&ncols,&row,&vals);

113:       MatGetRow(X,i,&ncols,&row,&vals);
114:       for (j=0; j<ncols; j++) {
115:         val[j] = a*vals[j];
116:       }
117:       MatSetValues(B,1,&i,ncols,row,val,ADD_VALUES);
118:       MatRestoreRow(X,i,&ncols,&row,&vals);
119:     }
120:     PetscFree(val);
121:   }
122:   MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
123:   MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
124:   return(0);
125: }

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

132:    Neighbor-wise Collective on Mat

134:    Input Parameters:
135: +  Y - the matrices
136: -  a - the PetscScalar 

138:    Level: intermediate

140: .keywords: matrix, add, shift

142: .seealso: MatDiagonalSet()
143:  @*/
144: PetscErrorCode  MatShift(Mat Y,PetscScalar a)
145: {
147:   PetscInt       i,start,end;

151:   if (!Y->assembled) SETERRQ(((PetscObject)Y)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
152:   if (Y->factortype) SETERRQ(((PetscObject)Y)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
153:   MatPreallocated(Y);

155:   if (Y->ops->shift) {
156:     (*Y->ops->shift)(Y,a);
157:   } else {
158:     PetscScalar alpha = a;
159:     MatGetOwnershipRange(Y,&start,&end);
160:     for (i=start; i<end; i++) {
161:       MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);
162:     }
163:     MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
164:     MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
165:   }
166:   return(0);
167: }

171: PetscErrorCode  MatDiagonalSet_Default(Mat Y,Vec D,InsertMode is)
172: {
174:   PetscInt       i,start,end,vstart,vend;
175:   PetscScalar    *v;

178:   VecGetOwnershipRange(D,&vstart,&vend);
179:   MatGetOwnershipRange(Y,&start,&end);
180:   if (vstart != start || vend != end) {
181:     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %D %D vec %D %D mat",vstart,vend,start,end);
182:   }
183:   VecGetArray(D,&v);
184:   for (i=start; i<end; i++) {
185:     MatSetValues(Y,1,&i,1,&i,v+i-start,is);
186:   }
187:   VecRestoreArray(D,&v);
188:   MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
189:   MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
190:   return(0);
191: }

195: /*@
196:    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
197:    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
198:    INSERT_VALUES.

200:    Input Parameters:
201: +  Y - the input matrix
202: .  D - the diagonal matrix, represented as a vector
203: -  i - INSERT_VALUES or ADD_VALUES

205:    Neighbor-wise Collective on Mat and Vec

207:    Level: intermediate

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

211: .seealso: MatShift()
212: @*/
213: PetscErrorCode  MatDiagonalSet(Mat Y,Vec D,InsertMode is)
214: {

220:   if (Y->ops->diagonalset) {
221:     (*Y->ops->diagonalset)(Y,D,is);
222:   } else {
223:     MatDiagonalSet_Default(Y,D,is);
224:   }
225:   return(0);
226: }

230: /*@
231:    MatAYPX - Computes Y = a*Y + X.

233:    Logically on Mat

235:    Input Parameters:
236: +  a - the PetscScalar multiplier
237: .  Y - the first matrix
238: .  X - the second matrix
239: -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN 

241:    Level: intermediate

243: .keywords: matrix, add

245: .seealso: MatAXPY()
246:  @*/
247: PetscErrorCode  MatAYPX(Mat Y,PetscScalar a,Mat X,MatStructure str)
248: {
249:   PetscScalar    one = 1.0;
251:   PetscInt       mX,mY,nX,nY;

257:   MatGetSize(X,&mX,&nX);
258:   MatGetSize(X,&mY,&nY);
259:   if (mX != mY || nX != nY) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Non conforming matrices: %D %D first %D %D second",mX,mY,nX,nY);

261:   MatScale(Y,a);
262:   MatAXPY(Y,one,X,str);
263:   return(0);
264: }

268: /*@
269:     MatComputeExplicitOperator - Computes the explicit matrix

271:     Collective on Mat

273:     Input Parameter:
274: .   inmat - the matrix

276:     Output Parameter:
277: .   mat - the explict preconditioned operator

279:     Notes:
280:     This computation is done by applying the operators to columns of the 
281:     identity matrix.

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

287:     Level: advanced
288:    
289: .keywords: Mat, compute, explicit, operator

291: @*/
292: PetscErrorCode  MatComputeExplicitOperator(Mat inmat,Mat *mat)
293: {
294:   Vec            in,out;
296:   PetscInt       i,m,n,M,N,*rows,start,end;
297:   MPI_Comm       comm;
298:   PetscScalar    *array,zero = 0.0,one = 1.0;
299:   PetscMPIInt    size;


305:   comm = ((PetscObject)inmat)->comm;
306:   MPI_Comm_size(comm,&size);

308:   MatGetLocalSize(inmat,&m,&n);
309:   MatGetSize(inmat,&M,&N);
310:   MatGetVecs(inmat,&in,&out);
311:   VecSetOption(in,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);
312:   VecGetOwnershipRange(out,&start,&end);
313:   PetscMalloc(m*sizeof(PetscInt),&rows);
314:   for (i=0; i<m; i++) {rows[i] = start + i;}

316:   MatCreate(comm,mat);
317:   MatSetSizes(*mat,m,n,M,N);
318:   if (size == 1) {
319:     MatSetType(*mat,MATSEQDENSE);
320:     MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
321:   } else {
322:     MatSetType(*mat,MATMPIAIJ);
323:     MatMPIAIJSetPreallocation(*mat,n,PETSC_NULL,N-n,PETSC_NULL);
324:   }

326:   for (i=0; i<N; i++) {

328:     VecSet(in,zero);
329:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
330:     VecAssemblyBegin(in);
331:     VecAssemblyEnd(in);

333:     MatMult(inmat,in,out);

335:     VecGetArray(out,&array);
336:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
337:     VecRestoreArray(out,&array);

339:   }
340:   PetscFree(rows);
341:   VecDestroy(&out);
342:   VecDestroy(&in);
343:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
344:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
345:   return(0);
346: }

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

357:   PetscMalloc(xi[m]*sizeof(PetscInt),&x2y);
358:   i = 0;
359:   for (row=0; row<m; row++){
360:     nz = xi[1] - xi[0];
361:     jy = 0;
362:     for (jx=0; jx<nz; jx++,jy++){
363:       if (xgarray && ygarray){
364:         xcol = xgarray[xj[*xi + jx]];
365:         ycol = ygarray[yj[*yi + jy]];
366:       } else {
367:         xcol = xj[*xi + jx];
368:         ycol = yj[*yi + jy];  /* col index for y */
369:       }
370:       while ( ycol < xcol ) {
371:         jy++;
372:         if (ygarray){
373:           ycol = ygarray[yj[*yi + jy]];
374:         } else {
375:           ycol = yj[*yi + jy];
376:         }
377:       }
378:       if (xcol != ycol) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"X matrix entry (%D,%D) is not in Y matrix",row,ycol);
379:       x2y[i++] = *yi + jy;
380:     }
381:     xi++; yi++;
382:   }
383:   *xtoy = x2y;
384:   return(0);
385: }