xref: /petsc/src/mat/utils/axpy.c (revision d083f849a86f1f43e18d534ee43954e2786cb29a)
16f79c3a4SBarry Smith 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>  /*I   "petscmat.h"  I*/
36f79c3a4SBarry Smith 
4d54c938cSPierre Jolivet static PetscErrorCode MatTransposeAXPY_Private(Mat Y,PetscScalar a,Mat X,MatStructure str,Mat T)
5d54c938cSPierre Jolivet {
6d54c938cSPierre Jolivet   PetscErrorCode ierr,(*f)(Mat,Mat*);
7d54c938cSPierre Jolivet   Mat            A,F;
8d54c938cSPierre Jolivet 
9d54c938cSPierre Jolivet   PetscFunctionBegin;
10d54c938cSPierre Jolivet   ierr = PetscObjectQueryFunction((PetscObject)T,"MatTransposeGetMat_C",&f);CHKERRQ(ierr);
11d54c938cSPierre Jolivet   if (f) {
12d54c938cSPierre Jolivet     ierr = MatTransposeGetMat(T,&A);CHKERRQ(ierr);
13d54c938cSPierre Jolivet     if (T == X) {
14d54c938cSPierre Jolivet       ierr = PetscInfo(NULL,"Explicitly transposing X of type MATTRANSPOSEMAT to perform MatAXPY()\n");CHKERRQ(ierr);
15d54c938cSPierre Jolivet       ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&F);CHKERRQ(ierr);
16d54c938cSPierre Jolivet       A = Y;
17d54c938cSPierre Jolivet     } else {
18d54c938cSPierre Jolivet       ierr = PetscInfo(NULL,"Transposing X because Y of type MATTRANSPOSEMAT to perform MatAXPY()\n");CHKERRQ(ierr);
19d54c938cSPierre Jolivet       ierr = MatTranspose(X,MAT_INITIAL_MATRIX,&F);CHKERRQ(ierr);
20d54c938cSPierre Jolivet     }
21d54c938cSPierre Jolivet   } else {
22d54c938cSPierre Jolivet     ierr = MatHermitianTransposeGetMat(T,&A);CHKERRQ(ierr);
23d54c938cSPierre Jolivet     if (T == X) {
24d54c938cSPierre Jolivet       ierr = PetscInfo(NULL,"Explicitly Hermitian transposing X of type MATTRANSPOSEMAT to perform MatAXPY()\n");CHKERRQ(ierr);
25d54c938cSPierre Jolivet       ierr = MatHermitianTranspose(A,MAT_INITIAL_MATRIX,&F);CHKERRQ(ierr);
26d54c938cSPierre Jolivet       A = Y;
27d54c938cSPierre Jolivet     } else {
28d54c938cSPierre Jolivet       ierr = PetscInfo(NULL,"Hermitian transposing X because Y of type MATTRANSPOSEMAT to perform MatAXPY()\n");CHKERRQ(ierr);
29d54c938cSPierre Jolivet       ierr = MatHermitianTranspose(X,MAT_INITIAL_MATRIX,&F);CHKERRQ(ierr);
30d54c938cSPierre Jolivet     }
31d54c938cSPierre Jolivet   }
32d54c938cSPierre Jolivet   ierr = MatAXPY(A,a,F,str);CHKERRQ(ierr);
33d54c938cSPierre Jolivet   ierr = MatDestroy(&F);CHKERRQ(ierr);
34d54c938cSPierre Jolivet   PetscFunctionReturn(0);
35d54c938cSPierre Jolivet }
36d54c938cSPierre Jolivet 
3706be10caSBarry Smith /*@
3821c89e3eSBarry Smith    MatAXPY - Computes Y = a*X + Y.
396f79c3a4SBarry Smith 
403f9fe445SBarry Smith    Logically  Collective on Mat
41fee21e36SBarry Smith 
4298a79cdbSBarry Smith    Input Parameters:
43607cd303SBarry Smith +  a - the scalar multiplier
44607cd303SBarry Smith .  X - the first matrix
45607cd303SBarry Smith .  Y - the second matrix
46407f6b05SHong Zhang -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN
47407f6b05SHong Zhang          or SUBSET_NONZERO_PATTERN (nonzeros of X is a subset of Y's)
4898a79cdbSBarry Smith 
492860a424SLois Curfman McInnes    Level: intermediate
502860a424SLois Curfman McInnes 
512860a424SLois Curfman McInnes .seealso: MatAYPX()
5206be10caSBarry Smith  @*/
537087cfbeSBarry Smith PetscErrorCode MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str)
546f79c3a4SBarry Smith {
55d54c938cSPierre Jolivet   PetscErrorCode ierr;
56646531bbSStefano Zampini   PetscInt       M1,M2,N1,N2;
57c1ac3661SBarry Smith   PetscInt       m1,m2,n1,n2;
58a683ea4aSPierre Jolivet   MatType        t1,t2;
59a683ea4aSPierre Jolivet   PetscBool      sametype,transpose;
606f79c3a4SBarry Smith 
613a40ed3dSBarry Smith   PetscFunctionBegin;
620700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
63c5eb9154SBarry Smith   PetscValidLogicalCollectiveScalar(Y,a,2);
64646531bbSStefano Zampini   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
65646531bbSStefano Zampini   PetscCheckSameComm(Y,1,X,3);
66646531bbSStefano Zampini   ierr = MatGetSize(X,&M1,&N1);CHKERRQ(ierr);
67646531bbSStefano Zampini   ierr = MatGetSize(Y,&M2,&N2);CHKERRQ(ierr);
68646531bbSStefano Zampini   ierr = MatGetLocalSize(X,&m1,&n1);CHKERRQ(ierr);
69646531bbSStefano Zampini   ierr = MatGetLocalSize(Y,&m2,&n2);CHKERRQ(ierr);
70646531bbSStefano Zampini   if (M1 != M2 || N1 != N2) SETERRQ4(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_SIZ,"Non conforming matrix add: global sizes %D x %D, %D x %D",M1,M2,N1,N2);
71646531bbSStefano Zampini   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Non conforming matrix add: local sizes %D x %D, %D x %D",m1,m2,n1,n2);
721987afe7SBarry Smith 
73a683ea4aSPierre Jolivet   ierr = MatGetType(X,&t1);CHKERRQ(ierr);
74a683ea4aSPierre Jolivet   ierr = MatGetType(Y,&t2);CHKERRQ(ierr);
75a683ea4aSPierre Jolivet   ierr = PetscStrcmp(t1,t2,&sametype);CHKERRQ(ierr);
76e8136da8SHong Zhang   ierr = PetscLogEventBegin(MAT_AXPY,Y,0,0,0);CHKERRQ(ierr);
770ff8bee4SStefano Zampini   if (Y->ops->axpy && sametype) {
78f4df32b1SMatthew Knepley     ierr = (*Y->ops->axpy)(Y,a,X,str);CHKERRQ(ierr);
79d4bb536fSBarry Smith   } else {
80a683ea4aSPierre Jolivet     ierr = PetscStrcmp(t1,MATTRANSPOSEMAT,&transpose);CHKERRQ(ierr);
81a683ea4aSPierre Jolivet     if (transpose) {
82d54c938cSPierre Jolivet         ierr = MatTransposeAXPY_Private(Y,a,X,str,X);CHKERRQ(ierr);
83a683ea4aSPierre Jolivet     } else {
84a683ea4aSPierre Jolivet       ierr = PetscStrcmp(t2,MATTRANSPOSEMAT,&transpose);CHKERRQ(ierr);
85a683ea4aSPierre Jolivet       if (transpose) {
86d54c938cSPierre Jolivet         ierr = MatTransposeAXPY_Private(Y,a,X,str,Y);CHKERRQ(ierr);
87a683ea4aSPierre Jolivet       } else {
88646531bbSStefano Zampini         if (str != DIFFERENT_NONZERO_PATTERN) {
89f4df32b1SMatthew Knepley           ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
90646531bbSStefano Zampini         } else {
91646531bbSStefano Zampini           Mat B;
92646531bbSStefano Zampini 
93646531bbSStefano Zampini           ierr = MatAXPY_Basic_Preallocate(Y,X,&B);CHKERRQ(ierr);
94646531bbSStefano Zampini           ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
95646531bbSStefano Zampini           ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
96646531bbSStefano Zampini         }
97607cd303SBarry Smith       }
98a683ea4aSPierre Jolivet     }
99a683ea4aSPierre Jolivet   }
100e8136da8SHong Zhang   ierr = PetscLogEventEnd(MAT_AXPY,Y,0,0,0);CHKERRQ(ierr);
101fd314934SBarry Smith #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
102b8ced49eSKarl Rupp   if (Y->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
103b8ced49eSKarl Rupp     Y->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
104c41cb2e2SAlejandro Lamas Daviña   }
105d67ff14aSKarl Rupp #endif
106607cd303SBarry Smith   PetscFunctionReturn(0);
107607cd303SBarry Smith }
108607cd303SBarry Smith 
109646531bbSStefano Zampini PetscErrorCode MatAXPY_Basic_Preallocate(Mat Y, Mat X, Mat *B)
110646531bbSStefano Zampini {
111646531bbSStefano Zampini   PetscErrorCode ierr;
11227afe9e8SStefano Zampini   PetscErrorCode (*preall)(Mat,Mat,Mat*) = NULL;
113646531bbSStefano Zampini 
114646531bbSStefano Zampini   PetscFunctionBegin;
115646531bbSStefano Zampini   /* look for any available faster alternative to the general preallocator */
116646531bbSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)Y,"MatAXPYGetPreallocation_C",&preall);CHKERRQ(ierr);
117646531bbSStefano Zampini   if (preall) {
118646531bbSStefano Zampini     ierr = (*preall)(Y,X,B);CHKERRQ(ierr);
119646531bbSStefano Zampini   } else { /* Use MatPrellocator, assumes same row-col distribution */
120646531bbSStefano Zampini     Mat      preallocator;
121646531bbSStefano Zampini     PetscInt r,rstart,rend;
122646531bbSStefano Zampini     PetscInt m,n,M,N;
123646531bbSStefano Zampini 
1246eab9c35SStefano Zampini     ierr = MatGetRowUpperTriangular(Y);CHKERRQ(ierr);
1256eab9c35SStefano Zampini     ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr);
126646531bbSStefano Zampini     ierr = MatGetSize(Y,&M,&N);CHKERRQ(ierr);
127646531bbSStefano Zampini     ierr = MatGetLocalSize(Y,&m,&n);CHKERRQ(ierr);
128646531bbSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&preallocator);CHKERRQ(ierr);
129646531bbSStefano Zampini     ierr = MatSetType(preallocator,MATPREALLOCATOR);CHKERRQ(ierr);
130646531bbSStefano Zampini     ierr = MatSetSizes(preallocator,m,n,M,N);CHKERRQ(ierr);
131646531bbSStefano Zampini     ierr = MatSetUp(preallocator);CHKERRQ(ierr);
132646531bbSStefano Zampini     ierr = MatGetOwnershipRange(preallocator,&rstart,&rend);CHKERRQ(ierr);
133646531bbSStefano Zampini     for (r = rstart; r < rend; ++r) {
134646531bbSStefano Zampini       PetscInt          ncols;
135646531bbSStefano Zampini       const PetscInt    *row;
136646531bbSStefano Zampini       const PetscScalar *vals;
137646531bbSStefano Zampini 
138646531bbSStefano Zampini       ierr = MatGetRow(Y,r,&ncols,&row,&vals);CHKERRQ(ierr);
139646531bbSStefano Zampini       ierr = MatSetValues(preallocator,1,&r,ncols,row,vals,INSERT_VALUES);CHKERRQ(ierr);
140646531bbSStefano Zampini       ierr = MatRestoreRow(Y,r,&ncols,&row,&vals);CHKERRQ(ierr);
141646531bbSStefano Zampini       ierr = MatGetRow(X,r,&ncols,&row,&vals);CHKERRQ(ierr);
142646531bbSStefano Zampini       ierr = MatSetValues(preallocator,1,&r,ncols,row,vals,INSERT_VALUES);CHKERRQ(ierr);
143646531bbSStefano Zampini       ierr = MatRestoreRow(X,r,&ncols,&row,&vals);CHKERRQ(ierr);
144646531bbSStefano Zampini     }
145646531bbSStefano Zampini     ierr = MatAssemblyBegin(preallocator,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
146646531bbSStefano Zampini     ierr = MatAssemblyEnd(preallocator,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1476eab9c35SStefano Zampini     ierr = MatRestoreRowUpperTriangular(Y);CHKERRQ(ierr);
1486eab9c35SStefano Zampini     ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr);
149646531bbSStefano Zampini 
150646531bbSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)Y),B);CHKERRQ(ierr);
151646531bbSStefano Zampini     ierr = MatSetType(*B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
152646531bbSStefano Zampini     ierr = MatSetSizes(*B,m,n,M,N);CHKERRQ(ierr);
153646531bbSStefano Zampini     ierr = MatPreallocatorPreallocate(preallocator,PETSC_FALSE,*B);CHKERRQ(ierr);
154646531bbSStefano Zampini     ierr = MatDestroy(&preallocator);CHKERRQ(ierr);
155646531bbSStefano Zampini   }
156646531bbSStefano Zampini   PetscFunctionReturn(0);
157646531bbSStefano Zampini }
158646531bbSStefano Zampini 
159f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_Basic(Mat Y,PetscScalar a,Mat X,MatStructure str)
160607cd303SBarry Smith {
16138baddfdSBarry Smith   PetscInt          i,start,end,j,ncols,m,n;
1626849ba73SBarry Smith   PetscErrorCode    ierr;
16338baddfdSBarry Smith   const PetscInt    *row;
164b3cc6726SBarry Smith   PetscScalar       *val;
165b3cc6726SBarry Smith   const PetscScalar *vals;
166607cd303SBarry Smith 
167607cd303SBarry Smith   PetscFunctionBegin;
1688dadbd76SSatish Balay   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
16990f02eecSBarry Smith   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
1706eab9c35SStefano Zampini   ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr);
171f4df32b1SMatthew Knepley   if (a == 1.0) {
172d4bb536fSBarry Smith     for (i = start; i < end; i++) {
173d4bb536fSBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
174d4bb536fSBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
175d4bb536fSBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
176d4bb536fSBarry Smith     }
177d4bb536fSBarry Smith   } else {
17821a3365eSStefano Zampini     PetscInt vs = 100;
17921a3365eSStefano Zampini     /* realloc if needed, as this function may be used in parallel */
18021a3365eSStefano Zampini     ierr = PetscMalloc1(vs,&val);CHKERRQ(ierr);
18106be10caSBarry Smith     for (i=start; i<end; i++) {
182b3cc6726SBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
18321a3365eSStefano Zampini       if (vs < ncols) {
18421a3365eSStefano Zampini         vs   = PetscMin(2*ncols,n);
18521a3365eSStefano Zampini         ierr = PetscRealloc(vs*sizeof(*val),&val);CHKERRQ(ierr);
1866f79c3a4SBarry Smith       }
18721a3365eSStefano Zampini       for (j=0; j<ncols; j++) val[j] = a*vals[j];
188b3cc6726SBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,val,ADD_VALUES);CHKERRQ(ierr);
189b3cc6726SBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
1906f79c3a4SBarry Smith     }
191b3cc6726SBarry Smith     ierr = PetscFree(val);CHKERRQ(ierr);
192d4bb536fSBarry Smith   }
1936eab9c35SStefano Zampini   ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr);
1946d4a8577SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1956d4a8577SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1963a40ed3dSBarry Smith   PetscFunctionReturn(0);
1976f79c3a4SBarry Smith }
198052efed2SBarry Smith 
199ec7775f6SShri Abhyankar PetscErrorCode MatAXPY_BasicWithPreallocation(Mat B,Mat Y,PetscScalar a,Mat X,MatStructure str)
200ec7775f6SShri Abhyankar {
201ec7775f6SShri Abhyankar   PetscInt          i,start,end,j,ncols,m,n;
202ec7775f6SShri Abhyankar   PetscErrorCode    ierr;
203ec7775f6SShri Abhyankar   const PetscInt    *row;
204ec7775f6SShri Abhyankar   PetscScalar       *val;
205ec7775f6SShri Abhyankar   const PetscScalar *vals;
206ec7775f6SShri Abhyankar 
207ec7775f6SShri Abhyankar   PetscFunctionBegin;
208ec7775f6SShri Abhyankar   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
209ec7775f6SShri Abhyankar   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
2106eab9c35SStefano Zampini   ierr = MatGetRowUpperTriangular(Y);CHKERRQ(ierr);
2116eab9c35SStefano Zampini   ierr = MatGetRowUpperTriangular(X);CHKERRQ(ierr);
212ec7775f6SShri Abhyankar   if (a == 1.0) {
213ec7775f6SShri Abhyankar     for (i = start; i < end; i++) {
214ec7775f6SShri Abhyankar       ierr = MatGetRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
215ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
216ec7775f6SShri Abhyankar       ierr = MatRestoreRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
217ec7775f6SShri Abhyankar 
218ec7775f6SShri Abhyankar       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
219ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
220ec7775f6SShri Abhyankar       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
221ec7775f6SShri Abhyankar     }
222ec7775f6SShri Abhyankar   } else {
22321a3365eSStefano Zampini     PetscInt vs = 100;
22421a3365eSStefano Zampini     /* realloc if needed, as this function may be used in parallel */
22521a3365eSStefano Zampini     ierr = PetscMalloc1(vs,&val);CHKERRQ(ierr);
226ec7775f6SShri Abhyankar     for (i=start; i<end; i++) {
227ec7775f6SShri Abhyankar       ierr = MatGetRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
228ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
229ec7775f6SShri Abhyankar       ierr = MatRestoreRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
230ec7775f6SShri Abhyankar 
231ec7775f6SShri Abhyankar       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
23221a3365eSStefano Zampini       if (vs < ncols) {
23321a3365eSStefano Zampini         vs   = PetscMin(2*ncols,n);
23421a3365eSStefano Zampini         ierr = PetscRealloc(vs*sizeof(*val),&val);CHKERRQ(ierr);
235ec7775f6SShri Abhyankar       }
23621a3365eSStefano Zampini       for (j=0; j<ncols; j++) val[j] = a*vals[j];
237ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,val,ADD_VALUES);CHKERRQ(ierr);
238ec7775f6SShri Abhyankar       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
239ec7775f6SShri Abhyankar     }
240ec7775f6SShri Abhyankar     ierr = PetscFree(val);CHKERRQ(ierr);
241ec7775f6SShri Abhyankar   }
2426eab9c35SStefano Zampini   ierr = MatRestoreRowUpperTriangular(Y);CHKERRQ(ierr);
2436eab9c35SStefano Zampini   ierr = MatRestoreRowUpperTriangular(X);CHKERRQ(ierr);
244ec7775f6SShri Abhyankar   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
245ec7775f6SShri Abhyankar   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
246ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
247ec7775f6SShri Abhyankar }
248ec7775f6SShri Abhyankar 
249052efed2SBarry Smith /*@
25087828ca2SBarry Smith    MatShift - Computes Y =  Y + a I, where a is a PetscScalar and I is the identity matrix.
251052efed2SBarry Smith 
2523f9fe445SBarry Smith    Neighbor-wise Collective on Mat
253fee21e36SBarry Smith 
25498a79cdbSBarry Smith    Input Parameters:
25598a79cdbSBarry Smith +  Y - the matrices
25687828ca2SBarry Smith -  a - the PetscScalar
25798a79cdbSBarry Smith 
2582860a424SLois Curfman McInnes    Level: intermediate
2592860a424SLois Curfman McInnes 
26095452b02SPatrick Sanan    Notes:
26195452b02SPatrick Sanan     If the matrix Y is missing some diagonal entries this routine can be very slow. To make it fast one should initially
2626f33a894SBarry Smith    fill the matrix so that all diagonal entries have a value (with a value of zero for those locations that would not have an
2636f33a894SBarry Smith    entry).
2646f33a894SBarry Smith 
2650c0fd78eSBarry Smith    To form Y = Y + diag(V) use MatDiagonalSet()
2660c0fd78eSBarry Smith 
2676f33a894SBarry Smith    Developers Note: If the local "diagonal part" of the matrix Y has no entries then the local diagonal part is
2686f33a894SBarry Smith     preallocated with 1 nonzero per row for the to be added values. This allows for fast shifting of an empty matrix.
2696f33a894SBarry Smith 
2700c0fd78eSBarry Smith .seealso: MatDiagonalSet(), MatScale(), MatDiagonalScale()
271052efed2SBarry Smith  @*/
2727087cfbeSBarry Smith PetscErrorCode  MatShift(Mat Y,PetscScalar a)
273052efed2SBarry Smith {
2746849ba73SBarry Smith   PetscErrorCode ierr;
275052efed2SBarry Smith 
2763a40ed3dSBarry Smith   PetscFunctionBegin;
2770700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
278ce94432eSBarry Smith   if (!Y->assembled) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
279ce94432eSBarry Smith   if (Y->factortype) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2804994cf47SJed Brown   MatCheckPreallocated(Y,1);
2811b71c1a7SBarry Smith   if (a == 0.0) PetscFunctionReturn(0);
282b50b34bdSBarry Smith 
2831c738b47SStefano Zampini   if (Y->ops->shift) {
284f4df32b1SMatthew Knepley     ierr = (*Y->ops->shift)(Y,a);CHKERRQ(ierr);
2851c738b47SStefano Zampini   } else {
2861c738b47SStefano Zampini     ierr = MatShift_Basic(Y,a);CHKERRQ(ierr);
2871c738b47SStefano Zampini   }
2887d68702bSBarry Smith 
2895528ad4fSTristan Konolige   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
290fd314934SBarry Smith #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
291b8ced49eSKarl Rupp   if (Y->valid_GPU_matrix != PETSC_OFFLOAD_UNALLOCATED) {
292b8ced49eSKarl Rupp     Y->valid_GPU_matrix = PETSC_OFFLOAD_CPU;
293c41cb2e2SAlejandro Lamas Daviña   }
294d67ff14aSKarl Rupp #endif
2953a40ed3dSBarry Smith   PetscFunctionReturn(0);
296052efed2SBarry Smith }
2976d84be18SBarry Smith 
2987087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_Default(Mat Y,Vec D,InsertMode is)
29909f38230SBarry Smith {
30009f38230SBarry Smith   PetscErrorCode ierr;
30167576b8bSBarry Smith   PetscInt       i,start,end;
30209f38230SBarry Smith   PetscScalar    *v;
30309f38230SBarry Smith 
30409f38230SBarry Smith   PetscFunctionBegin;
30509f38230SBarry Smith   ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
30609f38230SBarry Smith   ierr = VecGetArray(D,&v);CHKERRQ(ierr);
30709f38230SBarry Smith   for (i=start; i<end; i++) {
30809f38230SBarry Smith     ierr = MatSetValues(Y,1,&i,1,&i,v+i-start,is);CHKERRQ(ierr);
30909f38230SBarry Smith   }
31009f38230SBarry Smith   ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
31109f38230SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31209f38230SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31309f38230SBarry Smith   PetscFunctionReturn(0);
31409f38230SBarry Smith }
31509f38230SBarry Smith 
3166d84be18SBarry Smith /*@
317f56f2b3fSBarry Smith    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
318f56f2b3fSBarry Smith    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
319f56f2b3fSBarry Smith    INSERT_VALUES.
3206d84be18SBarry Smith 
3216d84be18SBarry Smith    Input Parameters:
32298a79cdbSBarry Smith +  Y - the input matrix
323f56f2b3fSBarry Smith .  D - the diagonal matrix, represented as a vector
324f56f2b3fSBarry Smith -  i - INSERT_VALUES or ADD_VALUES
3256d84be18SBarry Smith 
326*d083f849SBarry Smith    Neighbor-wise Collective on Mat
327fee21e36SBarry Smith 
32895452b02SPatrick Sanan    Notes:
32995452b02SPatrick Sanan     If the matrix Y is missing some diagonal entries this routine can be very slow. To make it fast one should initially
3306f33a894SBarry Smith    fill the matrix so that all diagonal entries have a value (with a value of zero for those locations that would not have an
3316f33a894SBarry Smith    entry).
3326f33a894SBarry Smith 
3332860a424SLois Curfman McInnes    Level: intermediate
3342860a424SLois Curfman McInnes 
3350c0fd78eSBarry Smith .seealso: MatShift(), MatScale(), MatDiagonalScale()
3366d84be18SBarry Smith @*/
3377087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet(Mat Y,Vec D,InsertMode is)
3386d84be18SBarry Smith {
3396849ba73SBarry Smith   PetscErrorCode ierr;
34067576b8bSBarry Smith   PetscInt       matlocal,veclocal;
3416d84be18SBarry Smith 
3423a40ed3dSBarry Smith   PetscFunctionBegin;
3430700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
3440700a824SBarry Smith   PetscValidHeaderSpecific(D,VEC_CLASSID,2);
34567576b8bSBarry Smith   ierr = MatGetLocalSize(Y,&matlocal,NULL);CHKERRQ(ierr);
34667576b8bSBarry Smith   ierr = VecGetLocalSize(D,&veclocal);CHKERRQ(ierr);
34767576b8bSBarry Smith   if (matlocal != veclocal) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number local rows of matrix %D does not match that of vector for diagonal %D",matlocal,veclocal);
348f56f2b3fSBarry Smith   if (Y->ops->diagonalset) {
349f56f2b3fSBarry Smith     ierr = (*Y->ops->diagonalset)(Y,D,is);CHKERRQ(ierr);
35094d884c6SBarry Smith   } else {
35109f38230SBarry Smith     ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
3526d84be18SBarry Smith   }
3535528ad4fSTristan Konolige   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3543a40ed3dSBarry Smith   PetscFunctionReturn(0);
3556d84be18SBarry Smith }
356d4bb536fSBarry Smith 
357d4bb536fSBarry Smith /*@
35804aac2b0SHong Zhang    MatAYPX - Computes Y = a*Y + X.
359d4bb536fSBarry Smith 
3603f9fe445SBarry Smith    Logically on Mat
361fee21e36SBarry Smith 
36298a79cdbSBarry Smith    Input Parameters:
36304aac2b0SHong Zhang +  a - the PetscScalar multiplier
36404aac2b0SHong Zhang .  Y - the first matrix
36504aac2b0SHong Zhang .  X - the second matrix
36604aac2b0SHong Zhang -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
367d4bb536fSBarry Smith 
3682860a424SLois Curfman McInnes    Level: intermediate
3692860a424SLois Curfman McInnes 
3702860a424SLois Curfman McInnes .seealso: MatAXPY()
371d4bb536fSBarry Smith  @*/
3727087cfbeSBarry Smith PetscErrorCode  MatAYPX(Mat Y,PetscScalar a,Mat X,MatStructure str)
373d4bb536fSBarry Smith {
37487828ca2SBarry Smith   PetscScalar    one = 1.0;
3756849ba73SBarry Smith   PetscErrorCode ierr;
37638baddfdSBarry Smith   PetscInt       mX,mY,nX,nY;
377d4bb536fSBarry Smith 
3783a40ed3dSBarry Smith   PetscFunctionBegin;
379c5eb9154SBarry Smith   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
3800700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
381c5eb9154SBarry Smith   PetscValidLogicalCollectiveScalar(Y,a,2);
382329f5518SBarry Smith   ierr = MatGetSize(X,&mX,&nX);CHKERRQ(ierr);
383329f5518SBarry Smith   ierr = MatGetSize(X,&mY,&nY);CHKERRQ(ierr);
384e32f2f54SBarry Smith   if (mX != mY || nX != nY) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Non conforming matrices: %D %D first %D %D second",mX,mY,nX,nY);
385f4df32b1SMatthew Knepley   ierr = MatScale(Y,a);CHKERRQ(ierr);
386cb9801acSJed Brown   ierr = MatAXPY(Y,one,X,str);CHKERRQ(ierr);
3873a40ed3dSBarry Smith   PetscFunctionReturn(0);
388d4bb536fSBarry Smith }
389b0a32e0cSBarry Smith 
390b0a32e0cSBarry Smith /*@
3910bacdadaSStefano Zampini     MatComputeOperator - Computes the explicit matrix
392b0a32e0cSBarry Smith 
393b0a32e0cSBarry Smith     Collective on Mat
394b0a32e0cSBarry Smith 
395b0a32e0cSBarry Smith     Input Parameter:
396186a3e20SStefano Zampini +   inmat - the matrix
397186a3e20SStefano Zampini -   mattype - the matrix type for the explicit operator
398b0a32e0cSBarry Smith 
399b0a32e0cSBarry Smith     Output Parameter:
400f3b1f45cSBarry Smith .   mat - the explict  operator
401b0a32e0cSBarry Smith 
402b0a32e0cSBarry Smith     Notes:
403186a3e20SStefano Zampini     This computation is done by applying the operators to columns of the identity matrix.
404186a3e20SStefano Zampini     This routine is costly in general, and is recommended for use only with relatively small systems.
405186a3e20SStefano Zampini     Currently, this routine uses a dense matrix format if mattype == NULL.
406b0a32e0cSBarry Smith 
407b0a32e0cSBarry Smith     Level: advanced
408b0a32e0cSBarry Smith 
409b0a32e0cSBarry Smith @*/
4100bacdadaSStefano Zampini PetscErrorCode  MatComputeOperator(Mat inmat,MatType mattype,Mat *mat)
411b0a32e0cSBarry Smith {
412dfbe8321SBarry Smith   PetscErrorCode ierr;
413b0a32e0cSBarry Smith 
414b0a32e0cSBarry Smith   PetscFunctionBegin;
4150700a824SBarry Smith   PetscValidHeaderSpecific(inmat,MAT_CLASSID,1);
416186a3e20SStefano Zampini   PetscValidPointer(mat,3);
417186a3e20SStefano Zampini   ierr = MatConvert_Shell(inmat,mattype ? mattype : MATDENSE,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
41824f910e3SHong Zhang   PetscFunctionReturn(0);
41924f910e3SHong Zhang }
4204325cce7SMatthew G Knepley 
4214325cce7SMatthew G Knepley /*@
4220bacdadaSStefano Zampini     MatComputeOperatorTranspose - Computes the explicit matrix representation of
423f3b1f45cSBarry Smith         a give matrix that can apply MatMultTranspose()
424f3b1f45cSBarry Smith 
425f3b1f45cSBarry Smith     Collective on Mat
426f3b1f45cSBarry Smith 
427f3b1f45cSBarry Smith     Input Parameter:
428f3b1f45cSBarry Smith .   inmat - the matrix
429f3b1f45cSBarry Smith 
430f3b1f45cSBarry Smith     Output Parameter:
431f3b1f45cSBarry Smith .   mat - the explict  operator transposed
432f3b1f45cSBarry Smith 
433f3b1f45cSBarry Smith     Notes:
434186a3e20SStefano Zampini     This computation is done by applying the transpose of the operator to columns of the identity matrix.
435186a3e20SStefano Zampini     This routine is costly in general, and is recommended for use only with relatively small systems.
436186a3e20SStefano Zampini     Currently, this routine uses a dense matrix format if mattype == NULL.
437f3b1f45cSBarry Smith 
438f3b1f45cSBarry Smith     Level: advanced
439f3b1f45cSBarry Smith 
440f3b1f45cSBarry Smith @*/
4410bacdadaSStefano Zampini PetscErrorCode  MatComputeOperatorTranspose(Mat inmat,MatType mattype,Mat *mat)
442f3b1f45cSBarry Smith {
443186a3e20SStefano Zampini   Mat            A;
444f3b1f45cSBarry Smith   PetscErrorCode ierr;
445f3b1f45cSBarry Smith 
446f3b1f45cSBarry Smith   PetscFunctionBegin;
447f3b1f45cSBarry Smith   PetscValidHeaderSpecific(inmat,MAT_CLASSID,1);
448186a3e20SStefano Zampini   PetscValidPointer(mat,3);
449186a3e20SStefano Zampini   ierr = MatCreateTranspose(inmat,&A);CHKERRQ(ierr);
450186a3e20SStefano Zampini   ierr = MatConvert_Shell(A,mattype ? mattype : MATDENSE,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
451186a3e20SStefano Zampini   ierr = MatDestroy(&A);CHKERRQ(ierr);
452f3b1f45cSBarry Smith   PetscFunctionReturn(0);
453f3b1f45cSBarry Smith }
454f3b1f45cSBarry Smith 
455f3b1f45cSBarry Smith /*@
4564325cce7SMatthew G Knepley   MatChop - Set all values in the matrix less than the tolerance to zero
4574325cce7SMatthew G Knepley 
4584325cce7SMatthew G Knepley   Input Parameters:
4594325cce7SMatthew G Knepley + A   - The matrix
4604325cce7SMatthew G Knepley - tol - The zero tolerance
4614325cce7SMatthew G Knepley 
4624325cce7SMatthew G Knepley   Output Parameters:
4634325cce7SMatthew G Knepley . A - The chopped matrix
4644325cce7SMatthew G Knepley 
4654325cce7SMatthew G Knepley   Level: intermediate
4664325cce7SMatthew G Knepley 
4674325cce7SMatthew G Knepley .seealso: MatCreate(), MatZeroEntries()
4683fc99919SSatish Balay  @*/
4694325cce7SMatthew G Knepley PetscErrorCode MatChop(Mat A, PetscReal tol)
4704325cce7SMatthew G Knepley {
4714325cce7SMatthew G Knepley   PetscScalar    *newVals;
4724325cce7SMatthew G Knepley   PetscInt       *newCols;
4734325cce7SMatthew G Knepley   PetscInt       rStart, rEnd, numRows, maxRows, r, colMax = 0;
4744325cce7SMatthew G Knepley   PetscErrorCode ierr;
4754325cce7SMatthew G Knepley 
4764325cce7SMatthew G Knepley   PetscFunctionBegin;
4774325cce7SMatthew G Knepley   ierr = MatGetOwnershipRange(A, &rStart, &rEnd);CHKERRQ(ierr);
4784325cce7SMatthew G Knepley   for (r = rStart; r < rEnd; ++r) {
4794325cce7SMatthew G Knepley     PetscInt ncols;
4804325cce7SMatthew G Knepley 
4810298fd71SBarry Smith     ierr   = MatGetRow(A, r, &ncols, NULL, NULL);CHKERRQ(ierr);
4824325cce7SMatthew G Knepley     colMax = PetscMax(colMax, ncols);CHKERRQ(ierr);
4830298fd71SBarry Smith     ierr   = MatRestoreRow(A, r, &ncols, NULL, NULL);CHKERRQ(ierr);
4844325cce7SMatthew G Knepley   }
4854325cce7SMatthew G Knepley   numRows = rEnd - rStart;
486b2566f29SBarry Smith   ierr    = MPIU_Allreduce(&numRows, &maxRows, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
487dcca6d9dSJed Brown   ierr    = PetscMalloc2(colMax,&newCols,colMax,&newVals);CHKERRQ(ierr);
4884325cce7SMatthew G Knepley   for (r = rStart; r < rStart+maxRows; ++r) {
4894325cce7SMatthew G Knepley     const PetscScalar *vals;
4904325cce7SMatthew G Knepley     const PetscInt    *cols;
491fad45679SMatthew G. Knepley     PetscInt           ncols, newcols, c;
4924325cce7SMatthew G Knepley 
4934325cce7SMatthew G Knepley     if (r < rEnd) {
4944325cce7SMatthew G Knepley       ierr = MatGetRow(A, r, &ncols, &cols, &vals);CHKERRQ(ierr);
4954325cce7SMatthew G Knepley       for (c = 0; c < ncols; ++c) {
4964325cce7SMatthew G Knepley         newCols[c] = cols[c];
4974325cce7SMatthew G Knepley         newVals[c] = PetscAbsScalar(vals[c]) < tol ? 0.0 : vals[c];
4984325cce7SMatthew G Knepley       }
499fad45679SMatthew G. Knepley       newcols = ncols;
5004325cce7SMatthew G Knepley       ierr = MatRestoreRow(A, r, &ncols, &cols, &vals);CHKERRQ(ierr);
501fad45679SMatthew G. Knepley       ierr = MatSetValues(A, 1, &r, newcols, newCols, newVals, INSERT_VALUES);CHKERRQ(ierr);
5024325cce7SMatthew G Knepley     }
5034325cce7SMatthew G Knepley     ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5044325cce7SMatthew G Knepley     ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5054325cce7SMatthew G Knepley   }
5064325cce7SMatthew G Knepley   ierr = PetscFree2(newCols,newVals);CHKERRQ(ierr);
5074325cce7SMatthew G Knepley   PetscFunctionReturn(0);
5084325cce7SMatthew G Knepley }
509