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