Actual source code: axpy.c

 2:  #include src/mat/matimpl.h

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

  9:    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 or SUBSET_NONZERO_PATTERN

 17:    Contributed by: Matthew Knepley

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

 22:    Level: intermediate

 24: .keywords: matrix, add

 26: .seealso: MatAYPX()
 27:  @*/
 28: PetscErrorCode MatAXPY(const PetscScalar *a,Mat X,Mat Y,MatStructure str)
 29: {
 31:   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 (X->ops->axpy) {
 43:     (*X->ops->axpy)(a,X,Y,str);
 44:   } else {
 45:     MatAXPY_Basic(a,X,Y,str);
 46:   }
 47:   return(0);
 48: }


 53: PetscErrorCode MatAXPY_Basic(const PetscScalar *a,Mat X,Mat Y,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 MatShift(const PetscScalar *a,Mat Y)
105: {
107:   PetscInt       i,start,end;

112:   MatPreallocated(Y);
113:   if (!Y->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
114:   if (Y->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
115:   if (Y->ops->shift) {
116:     (*Y->ops->shift)(a,Y);
117:   } else {
118:     MatGetOwnershipRange(Y,&start,&end);
119:     for (i=start; i<end; i++) {
120:       MatSetValues(Y,1,&i,1,&i,a,ADD_VALUES);
121:     }
122:     MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
123:     MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
124:   }
125:   return(0);
126: }

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

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

140:    Collective on Mat and Vec

142:    Level: intermediate

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

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

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

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

182:    Collective on Mat

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

188:    Contributed by: Matthew Knepley

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

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

195:    Level: intermediate

197: .keywords: matrix, add

199: .seealso: MatAXPY()
200:  @*/
201: PetscErrorCode MatAYPX(const PetscScalar *a,Mat X,Mat Y)
202: {
203:   PetscScalar    one = 1.0;
205:   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(a,Y);
217:   MatAXPY(&one,X,Y,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 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,m,m,M,M,mat);
272:   if (size == 1) {
273:     MatSetType(*mat,MATSEQDENSE);
274: #if !defined(PETSC_USE_64BIT_INT)
275:     MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
276: #endif
277:   } else {
278:     MatSetType(*mat,MATMPIAIJ);
279:     MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);
280:   }

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

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

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

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

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

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