Actual source code: axpy.c
1: /*$Id: axpy.c,v 1.54 2001/08/06 21:16:10 bsmith Exp bsmith $*/
3: #include src/mat/matimpl.h
5: /*@
6: MatAXPY - Computes Y = a*X + Y.
8: Collective on Mat
10: Input Parameters:
11: + a - the scalar multiplier
12: . X - the first matrix
13: . Y - the second matrix
14: - str - either SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
16: Contributed by: Matthew Knepley
18: Notes:
19: Will only be efficient if one has the SAME_NONZERO_PATTERN
21: Level: intermediate
23: .keywords: matrix, add
25: .seealso: MatAYPX()
26: @*/
27: int MatAXPY(PetscScalar *a,Mat X,Mat Y,MatStructure str)
28: {
29: int m1,m2,n1,n2,ierr;
36: MatGetSize(X,&m1,&n1);
37: MatGetSize(Y,&m2,&n2);
38: if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %d %d %d %d",m1,m2,n1,n2);
40: if (X->ops->axpy) {
41: (*X->ops->axpy)(a,X,Y,str);
42: } else {
43: MatAXPY_Basic(a,X,Y,str);
44: }
45: return(0);
46: }
49: int MatAXPY_Basic(PetscScalar *a,Mat X,Mat Y,MatStructure str)
50: {
51: int i,*row,start,end,j,ncols,ierr,m,n;
52: PetscScalar *val,*vals;
55: MatGetSize(X,&m,&n);
56: MatGetOwnershipRange(X,&start,&end);
57: if (*a == 1.0) {
58: for (i = start; i < end; i++) {
59: MatGetRow(X,i,&ncols,&row,&vals);
60: MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);
61: MatRestoreRow(X,i,&ncols,&row,&vals);
62: }
63: } else {
64: PetscMalloc((n+1)*sizeof(PetscScalar),&vals);
65: for (i=start; i<end; i++) {
66: MatGetRow(X,i,&ncols,&row,&val);
67: for (j=0; j<ncols; j++) {
68: vals[j] = (*a)*val[j];
69: }
70: MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);
71: MatRestoreRow(X,i,&ncols,&row,&val);
72: }
73: PetscFree(vals);
74: }
75: MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
76: MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
77: return(0);
78: }
80: /*@
81: MatShift - Computes Y = Y + a I, where a is a PetscScalar and I is the identity matrix.
83: Collective on Mat
85: Input Parameters:
86: + Y - the matrices
87: - a - the PetscScalar
89: Level: intermediate
91: .keywords: matrix, add, shift
93: .seealso: MatDiagonalSet()
94: @*/
95: int MatShift(PetscScalar *a,Mat Y)
96: {
97: int i,start,end,ierr;
102: if (Y->ops->shift) {
103: (*Y->ops->shift)(a,Y);
104: } else {
105: MatGetOwnershipRange(Y,&start,&end);
106: for (i=start; i<end; i++) {
107: MatSetValues(Y,1,&i,1,&i,a,ADD_VALUES);
108: }
109: MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
110: MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
111: }
112: return(0);
113: }
115: /*@
116: MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
117: that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
118: INSERT_VALUES.
120: Input Parameters:
121: + Y - the input matrix
122: . D - the diagonal matrix, represented as a vector
123: - i - INSERT_VALUES or ADD_VALUES
125: Collective on Mat and Vec
127: Level: intermediate
129: .keywords: matrix, add, shift, diagonal
131: .seealso: MatShift()
132: @*/
133: int MatDiagonalSet(Mat Y,Vec D,InsertMode is)
134: {
135: int i,start,end,ierr;
140: if (Y->ops->diagonalset) {
141: (*Y->ops->diagonalset)(Y,D,is);
142: } else {
143: int vstart,vend;
144: PetscScalar *v;
145: VecGetOwnershipRange(D,&vstart,&vend);
146: MatGetOwnershipRange(Y,&start,&end);
147: if (vstart != start || vend != end) {
148: SETERRQ4(PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %d %d vec %d %d mat",vstart,vend,start,end);
149: }
150: VecGetArray(D,&v);
151: for (i=start; i<end; i++) {
152: MatSetValues(Y,1,&i,1,&i,v+i-start,is);
153: }
154: VecRestoreArray(D,&v);
155: MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);
156: MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);
157: }
158: return(0);
159: }
161: /*@
162: MatAYPX - Computes Y = X + a*Y.
164: Collective on Mat
166: Input Parameters:
167: + X,Y - the matrices
168: - a - the PetscScalar multiplier
170: Contributed by: Matthew Knepley
172: Notes:
173: This routine currently uses the MatAXPY() implementation.
175: This is slow, if you need it fast send email to petsc-maint@mcs.anl.gov
177: Level: intermediate
179: .keywords: matrix, add
181: .seealso: MatAXPY()
182: @*/
183: int MatAYPX(PetscScalar *a,Mat X,Mat Y)
184: {
185: PetscScalar one = 1.0;
186: int mX,mY,nX,nY,ierr;
193: MatGetSize(X,&mX,&nX);
194: MatGetSize(X,&mY,&nY);
195: if (mX != mY || nX != nY) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrices: %d %d first %d %d second",mX,mY,nX,nY);
197: MatScale(a,Y);
198: MatAXPY(&one,X,Y,DIFFERENT_NONZERO_PATTERN);
199: return(0);
200: }
202: /*@
203: MatComputeExplicitOperator - Computes the explicit matrix
205: Collective on Mat
207: Input Parameter:
208: . inmat - the matrix
210: Output Parameter:
211: . mat - the explict preconditioned operator
213: Notes:
214: This computation is done by applying the operators to columns of the
215: identity matrix.
217: Currently, this routine uses a dense matrix format when 1 processor
218: is used and a sparse format otherwise. This routine is costly in general,
219: and is recommended for use only with relatively small systems.
221: Level: advanced
222:
223: .keywords: Mat, compute, explicit, operator
225: @*/
226: int MatComputeExplicitOperator(Mat inmat,Mat *mat)
227: {
228: Vec in,out;
229: int ierr,i,M,m,size,*rows,start,end;
230: MPI_Comm comm;
231: PetscScalar *array,zero = 0.0,one = 1.0;
237: comm = inmat->comm;
238: MPI_Comm_size(comm,&size);
240: MatGetLocalSize(inmat,&m,0);
241: MatGetSize(inmat,&M,0);
242: VecCreateMPI(comm,m,M,&in);
243: VecDuplicate(in,&out);
244: VecGetOwnershipRange(in,&start,&end);
245: PetscMalloc((m+1)*sizeof(int),&rows);
246: for (i=0; i<m; i++) {rows[i] = start + i;}
248: if (size == 1) {
249: MatCreateSeqDense(comm,M,M,PETSC_NULL,mat);
250: } else {
251: MatCreateMPIAIJ(comm,m,m,M,M,0,0,0,0,mat);
252: }
254: for (i=0; i<M; i++) {
256: VecSet(&zero,in);
257: VecSetValues(in,1,&i,&one,INSERT_VALUES);
258: VecAssemblyBegin(in);
259: VecAssemblyEnd(in);
261: MatMult(inmat,in,out);
262:
263: VecGetArray(out,&array);
264: MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
265: VecRestoreArray(out,&array);
267: }
268: PetscFree(rows);
269: VecDestroy(out);
270: VecDestroy(in);
271: MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
272: MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
273: return(0);
274: }