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