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