xref: /petsc/src/mat/utils/axpy.c (revision 9c30b7d2697335155d7490a7e085415ee7b4a02a)
1 
2 #include "src/mat/matimpl.h"  /*I   "petscmat.h"  I*/
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "MatAXPY"
6 /*@
7    MatAXPY - Computes Y = a*X + Y.
8 
9    Collective on Mat
10 
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
16 
17    Contributed by: Matthew Knepley
18 
19    Notes:
20      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
21 
22    Level: intermediate
23 
24 .keywords: matrix, add
25 
26 .seealso: MatAYPX()
27  @*/
28 int MatAXPY(const PetscScalar *a,Mat X,Mat Y,MatStructure str)
29 {
30   int         m1,m2,n1,n2,ierr;
31 
32   PetscFunctionBegin;
33   PetscValidScalarPointer(a,1);
34   PetscValidHeaderSpecific(X,MAT_COOKIE,2);
35   PetscValidHeaderSpecific(Y,MAT_COOKIE,3);
36 
37   ierr = MatGetSize(X,&m1,&n1);CHKERRQ(ierr);
38   ierr = MatGetSize(Y,&m2,&n2);CHKERRQ(ierr);
39   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %d %d %d %d",m1,m2,n1,n2);
40 
41   if (X->ops->axpy) {
42     ierr = (*X->ops->axpy)(a,X,Y,str);CHKERRQ(ierr);
43   } else {
44     ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr);
45   }
46   PetscFunctionReturn(0);
47 }
48 
49 
50 #undef __FUNCT__
51 #define __FUNCT__ "MatAXPY_Basic"
52 int MatAXPY_Basic(const PetscScalar *a,Mat X,Mat Y,MatStructure str)
53 {
54   int         i,*row,start,end,j,ncols,ierr,m,n;
55   PetscScalar *val,*vals;
56 
57   PetscFunctionBegin;
58   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
59   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
60   if (*a == 1.0) {
61     for (i = start; i < end; i++) {
62       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
63       ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
64       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
65     }
66   } else {
67     ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
68     for (i=start; i<end; i++) {
69       ierr = MatGetRow(X,i,&ncols,&row,&val);CHKERRQ(ierr);
70       for (j=0; j<ncols; j++) {
71 	vals[j] = (*a)*val[j];
72       }
73       ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
74       ierr = MatRestoreRow(X,i,&ncols,&row,&val);CHKERRQ(ierr);
75     }
76     ierr = PetscFree(vals);CHKERRQ(ierr);
77   }
78   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
79   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
80   PetscFunctionReturn(0);
81 }
82 
83 #undef __FUNCT__
84 #define __FUNCT__ "MatShift"
85 /*@
86    MatShift - Computes Y =  Y + a I, where a is a PetscScalar and I is the identity matrix.
87 
88    Collective on Mat
89 
90    Input Parameters:
91 +  Y - the matrices
92 -  a - the PetscScalar
93 
94    Level: intermediate
95 
96 .keywords: matrix, add, shift
97 
98 .seealso: MatDiagonalSet()
99  @*/
100 int MatShift(const PetscScalar *a,Mat Y)
101 {
102   int    i,start,end,ierr;
103 
104   PetscFunctionBegin;
105   PetscValidScalarPointer(a,1);
106   PetscValidHeaderSpecific(Y,MAT_COOKIE,2);
107   if (Y->ops->shift) {
108     ierr = (*Y->ops->shift)(a,Y);CHKERRQ(ierr);
109   } else {
110     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
111     for (i=start; i<end; i++) {
112       ierr = MatSetValues(Y,1,&i,1,&i,a,ADD_VALUES);CHKERRQ(ierr);
113     }
114     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
115     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
116   }
117   PetscFunctionReturn(0);
118 }
119 
120 #undef __FUNCT__
121 #define __FUNCT__ "MatDiagonalSet"
122 /*@
123    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
124    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
125    INSERT_VALUES.
126 
127    Input Parameters:
128 +  Y - the input matrix
129 .  D - the diagonal matrix, represented as a vector
130 -  i - INSERT_VALUES or ADD_VALUES
131 
132    Collective on Mat and Vec
133 
134    Level: intermediate
135 
136 .keywords: matrix, add, shift, diagonal
137 
138 .seealso: MatShift()
139 @*/
140 int MatDiagonalSet(Mat Y,Vec D,InsertMode is)
141 {
142   int    i,start,end,ierr;
143 
144   PetscFunctionBegin;
145   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
146   PetscValidHeaderSpecific(D,VEC_COOKIE,2);
147   if (Y->ops->diagonalset) {
148     ierr = (*Y->ops->diagonalset)(Y,D,is);CHKERRQ(ierr);
149   } else {
150     int    vstart,vend;
151     PetscScalar *v;
152     ierr = VecGetOwnershipRange(D,&vstart,&vend);CHKERRQ(ierr);
153     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
154     if (vstart != start || vend != end) {
155       SETERRQ4(PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %d %d vec %d %d mat",vstart,vend,start,end);
156     }
157     ierr = VecGetArray(D,&v);CHKERRQ(ierr);
158     for (i=start; i<end; i++) {
159       ierr = MatSetValues(Y,1,&i,1,&i,v+i-start,is);CHKERRQ(ierr);
160     }
161     ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
162     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
163     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
164   }
165   PetscFunctionReturn(0);
166 }
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "MatAYPX"
170 /*@
171    MatAYPX - Computes Y = X + a*Y.
172 
173    Collective on Mat
174 
175    Input Parameters:
176 +  X,Y - the matrices
177 -  a - the PetscScalar multiplier
178 
179    Contributed by: Matthew Knepley
180 
181    Notes:
182    This routine currently uses the MatAXPY() implementation.
183 
184    This is slow, if you need it fast send email to petsc-maint@mcs.anl.gov
185 
186    Level: intermediate
187 
188 .keywords: matrix, add
189 
190 .seealso: MatAXPY()
191  @*/
192 int MatAYPX(const PetscScalar *a,Mat X,Mat Y)
193 {
194   PetscScalar one = 1.0;
195   int         mX,mY,nX,nY,ierr;
196 
197   PetscFunctionBegin;
198   PetscValidScalarPointer(a,1);
199   PetscValidHeaderSpecific(X,MAT_COOKIE,2);
200   PetscValidHeaderSpecific(Y,MAT_COOKIE,3);
201 
202   ierr = MatGetSize(X,&mX,&nX);CHKERRQ(ierr);
203   ierr = MatGetSize(X,&mY,&nY);CHKERRQ(ierr);
204   if (mX != mY || nX != nY) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrices: %d %d first %d %d second",mX,mY,nX,nY);
205 
206   ierr = MatScale(a,Y);CHKERRQ(ierr);
207   ierr = MatAXPY(&one,X,Y,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "MatComputeExplicitOperator"
213 /*@
214     MatComputeExplicitOperator - Computes the explicit matrix
215 
216     Collective on Mat
217 
218     Input Parameter:
219 .   inmat - the matrix
220 
221     Output Parameter:
222 .   mat - the explict preconditioned operator
223 
224     Notes:
225     This computation is done by applying the operators to columns of the
226     identity matrix.
227 
228     Currently, this routine uses a dense matrix format when 1 processor
229     is used and a sparse format otherwise.  This routine is costly in general,
230     and is recommended for use only with relatively small systems.
231 
232     Level: advanced
233 
234 .keywords: Mat, compute, explicit, operator
235 
236 @*/
237 int MatComputeExplicitOperator(Mat inmat,Mat *mat)
238 {
239   Vec      in,out;
240   int      ierr,i,M,m,size,*rows,start,end;
241   MPI_Comm comm;
242   PetscScalar   *array,zero = 0.0,one = 1.0;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(inmat,MAT_COOKIE,1);
246   PetscValidPointer(mat,2);
247 
248   comm = inmat->comm;
249   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
250 
251   ierr = MatGetLocalSize(inmat,&m,0);CHKERRQ(ierr);
252   ierr = MatGetSize(inmat,&M,0);CHKERRQ(ierr);
253   ierr = VecCreateMPI(comm,m,M,&in);CHKERRQ(ierr);
254   ierr = VecDuplicate(in,&out);CHKERRQ(ierr);
255   ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr);
256   ierr = PetscMalloc((m+1)*sizeof(int),&rows);CHKERRQ(ierr);
257   for (i=0; i<m; i++) {rows[i] = start + i;}
258 
259   ierr = MatCreate(comm,m,m,M,M,mat);CHKERRQ(ierr);
260   if (size == 1) {
261     ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr);
262     ierr = MatSeqDenseSetPreallocation(*mat,PETSC_NULL);CHKERRQ(ierr);
263   } else {
264     ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
265     ierr = MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
266   }
267 
268   for (i=0; i<M; i++) {
269 
270     ierr = VecSet(&zero,in);CHKERRQ(ierr);
271     ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr);
272     ierr = VecAssemblyBegin(in);CHKERRQ(ierr);
273     ierr = VecAssemblyEnd(in);CHKERRQ(ierr);
274 
275     ierr = MatMult(inmat,in,out);CHKERRQ(ierr);
276 
277     ierr = VecGetArray(out,&array);CHKERRQ(ierr);
278     ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
279     ierr = VecRestoreArray(out,&array);CHKERRQ(ierr);
280 
281   }
282   ierr = PetscFree(rows);CHKERRQ(ierr);
283   ierr = VecDestroy(out);CHKERRQ(ierr);
284   ierr = VecDestroy(in);CHKERRQ(ierr);
285   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
286   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
287   PetscFunctionReturn(0);
288 }
289 
290 /* Get the map xtoy which is used by MatAXPY() in the case of SUBSET_NONZERO_PATTERN */
291 #undef __FUNCT__
292 #define __FUNCT__ "MatAXPYGetxtoy_Private"
293 int MatAXPYGetxtoy_Private(int m,int *xi,int *xj,int *xgarray, int *yi,int *yj,int *ygarray, int **xtoy)
294 {
295   int ierr,row,i,nz,xcol,ycol,jx,jy,*x2y;
296 
297   PetscFunctionBegin;
298   ierr = PetscMalloc(xi[m]*sizeof(int),&x2y);CHKERRQ(ierr);
299   i = 0;
300   for (row=0; row<m; row++){
301     nz = xi[1] - xi[0];
302     jy = 0;
303     for (jx=0; jx<nz; jx++,jy++){
304       if (xgarray && ygarray){
305         xcol = xgarray[xj[*xi + jx]];
306         ycol = ygarray[yj[*yi + jy]];
307       } else {
308         xcol = xj[*xi + jx];
309         ycol = yj[*yi + jy];  /* col index for y */
310       }
311       while ( ycol < xcol ) {
312         jy++;
313         if (ygarray){
314           ycol = ygarray[yj[*yi + jy]];
315         } else {
316           ycol = yj[*yi + jy];
317         }
318       }
319       if (xcol != ycol) SETERRQ2(PETSC_ERR_ARG_WRONG,"X matrix entry (%d,%d) is not in Y matrix",row,ycol);
320       x2y[i++] = *yi + jy;
321     }
322     xi++; yi++;
323   }
324   *xtoy = x2y;
325   PetscFunctionReturn(0);
326 }
327