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