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