xref: /petsc/src/mat/utils/axpy.c (revision ec7775f6eb19ff131f3f6f532f075e0eb450b618)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
26f79c3a4SBarry Smith 
37c4f633dSBarry Smith #include "private/matimpl.h"  /*I   "petscmat.h"  I*/
46f79c3a4SBarry Smith 
54a2ae208SSatish Balay #undef __FUNCT__
64a2ae208SSatish Balay #define __FUNCT__ "MatAXPY"
706be10caSBarry Smith /*@
821c89e3eSBarry Smith    MatAXPY - Computes Y = a*X + Y.
96f79c3a4SBarry Smith 
103f9fe445SBarry Smith    Logically  Collective on Mat
11fee21e36SBarry Smith 
1298a79cdbSBarry Smith    Input Parameters:
13607cd303SBarry Smith +  a - the scalar multiplier
14607cd303SBarry Smith .  X - the first matrix
15607cd303SBarry Smith .  Y - the second matrix
16407f6b05SHong Zhang -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN
17407f6b05SHong Zhang          or SUBSET_NONZERO_PATTERN (nonzeros of X is a subset of Y's)
1898a79cdbSBarry Smith 
192860a424SLois Curfman McInnes    Notes:
201a5ee19eSHong Zhang      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
212860a424SLois Curfman McInnes 
222860a424SLois Curfman McInnes    Level: intermediate
232860a424SLois Curfman McInnes 
249cf4f1e8SLois Curfman McInnes .keywords: matrix, add
25d4bb536fSBarry Smith 
262860a424SLois Curfman McInnes .seealso: MatAYPX()
2706be10caSBarry Smith  @*/
28f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str)
296f79c3a4SBarry Smith {
306849ba73SBarry Smith   PetscErrorCode ierr;
31c1ac3661SBarry Smith   PetscInt       m1,m2,n1,n2;
326f79c3a4SBarry Smith 
333a40ed3dSBarry Smith   PetscFunctionBegin;
340700a824SBarry Smith   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
350700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
36c5eb9154SBarry Smith   PetscValidLogicalCollectiveScalar(Y,a,2);
37273d9f13SBarry Smith   ierr = MatGetSize(X,&m1,&n1);CHKERRQ(ierr);
38273d9f13SBarry Smith   ierr = MatGetSize(Y,&m2,&n2);CHKERRQ(ierr);
39e32f2f54SBarry Smith   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %D %D %D %D",m1,m2,n1,n2);
401987afe7SBarry Smith 
41e8136da8SHong Zhang   ierr = PetscLogEventBegin(MAT_AXPY,Y,0,0,0);CHKERRQ(ierr);
42f4df32b1SMatthew Knepley   if (Y->ops->axpy) {
43f4df32b1SMatthew Knepley     ierr = (*Y->ops->axpy)(Y,a,X,str);CHKERRQ(ierr);
44d4bb536fSBarry Smith   } else {
45f4df32b1SMatthew Knepley     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
46607cd303SBarry Smith   }
47e8136da8SHong Zhang   ierr = PetscLogEventEnd(MAT_AXPY,Y,0,0,0);CHKERRQ(ierr);
48607cd303SBarry Smith   PetscFunctionReturn(0);
49607cd303SBarry Smith }
50607cd303SBarry Smith 
51607cd303SBarry Smith #undef __FUNCT__
52607cd303SBarry Smith #define __FUNCT__ "MatAXPY_Basic"
53f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_Basic(Mat Y,PetscScalar a,Mat X,MatStructure str)
54607cd303SBarry Smith {
5538baddfdSBarry Smith   PetscInt          i,start,end,j,ncols,m,n;
566849ba73SBarry Smith   PetscErrorCode    ierr;
5738baddfdSBarry Smith   const PetscInt    *row;
58b3cc6726SBarry Smith   PetscScalar       *val;
59b3cc6726SBarry Smith   const PetscScalar *vals;
60607cd303SBarry Smith 
61607cd303SBarry Smith   PetscFunctionBegin;
628dadbd76SSatish Balay   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
6390f02eecSBarry Smith   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
64f4df32b1SMatthew Knepley   if (a == 1.0) {
65d4bb536fSBarry Smith     for (i = start; i < end; i++) {
66d4bb536fSBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
67d4bb536fSBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
68d4bb536fSBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
69d4bb536fSBarry Smith     }
70d4bb536fSBarry Smith   } else {
71b3cc6726SBarry Smith     ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&val);CHKERRQ(ierr);
7206be10caSBarry Smith     for (i=start; i<end; i++) {
73b3cc6726SBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
7406be10caSBarry Smith       for (j=0; j<ncols; j++) {
75f4df32b1SMatthew Knepley 	val[j] = a*vals[j];
766f79c3a4SBarry Smith       }
77b3cc6726SBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,val,ADD_VALUES);CHKERRQ(ierr);
78b3cc6726SBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
796f79c3a4SBarry Smith     }
80b3cc6726SBarry Smith     ierr = PetscFree(val);CHKERRQ(ierr);
81d4bb536fSBarry Smith   }
826d4a8577SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
836d4a8577SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
843a40ed3dSBarry Smith   PetscFunctionReturn(0);
856f79c3a4SBarry Smith }
86052efed2SBarry Smith 
874a2ae208SSatish Balay #undef __FUNCT__
88*ec7775f6SShri Abhyankar #define __FUNCT__ "MatAXPY_BasicWithPreallocation"
89*ec7775f6SShri Abhyankar PetscErrorCode MatAXPY_BasicWithPreallocation(Mat B,Mat Y,PetscScalar a,Mat X,MatStructure str)
90*ec7775f6SShri Abhyankar {
91*ec7775f6SShri Abhyankar   PetscInt          i,start,end,j,ncols,m,n;
92*ec7775f6SShri Abhyankar   PetscErrorCode    ierr;
93*ec7775f6SShri Abhyankar   const PetscInt    *row;
94*ec7775f6SShri Abhyankar   PetscScalar       *val;
95*ec7775f6SShri Abhyankar   const PetscScalar *vals;
96*ec7775f6SShri Abhyankar 
97*ec7775f6SShri Abhyankar   PetscFunctionBegin;
98*ec7775f6SShri Abhyankar   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
99*ec7775f6SShri Abhyankar   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
100*ec7775f6SShri Abhyankar   if (a == 1.0) {
101*ec7775f6SShri Abhyankar     for (i = start; i < end; i++) {
102*ec7775f6SShri Abhyankar       ierr = MatGetRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
103*ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
104*ec7775f6SShri Abhyankar       ierr = MatRestoreRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
105*ec7775f6SShri Abhyankar 
106*ec7775f6SShri Abhyankar       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
107*ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
108*ec7775f6SShri Abhyankar       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
109*ec7775f6SShri Abhyankar     }
110*ec7775f6SShri Abhyankar   } else {
111*ec7775f6SShri Abhyankar     ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&val);CHKERRQ(ierr);
112*ec7775f6SShri Abhyankar     for (i=start; i<end; i++) {
113*ec7775f6SShri Abhyankar       ierr = MatGetRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
114*ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
115*ec7775f6SShri Abhyankar       ierr = MatRestoreRow(Y,i,&ncols,&row,&vals);CHKERRQ(ierr);
116*ec7775f6SShri Abhyankar 
117*ec7775f6SShri Abhyankar       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
118*ec7775f6SShri Abhyankar       for (j=0; j<ncols; j++) {
119*ec7775f6SShri Abhyankar 	val[j] = a*vals[j];
120*ec7775f6SShri Abhyankar       }
121*ec7775f6SShri Abhyankar       ierr = MatSetValues(B,1,&i,ncols,row,val,ADD_VALUES);CHKERRQ(ierr);
122*ec7775f6SShri Abhyankar       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
123*ec7775f6SShri Abhyankar     }
124*ec7775f6SShri Abhyankar     ierr = PetscFree(val);CHKERRQ(ierr);
125*ec7775f6SShri Abhyankar   }
126*ec7775f6SShri Abhyankar   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
127*ec7775f6SShri Abhyankar   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
128*ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
129*ec7775f6SShri Abhyankar }
130*ec7775f6SShri Abhyankar 
131*ec7775f6SShri Abhyankar #undef __FUNCT__
1324a2ae208SSatish Balay #define __FUNCT__ "MatShift"
133052efed2SBarry Smith /*@
13487828ca2SBarry Smith    MatShift - Computes Y =  Y + a I, where a is a PetscScalar and I is the identity matrix.
135052efed2SBarry Smith 
1363f9fe445SBarry Smith    Neighbor-wise Collective on Mat
137fee21e36SBarry Smith 
13898a79cdbSBarry Smith    Input Parameters:
13998a79cdbSBarry Smith +  Y - the matrices
14087828ca2SBarry Smith -  a - the PetscScalar
14198a79cdbSBarry Smith 
1422860a424SLois Curfman McInnes    Level: intermediate
1432860a424SLois Curfman McInnes 
144052efed2SBarry Smith .keywords: matrix, add, shift
1456b9ee512SLois Curfman McInnes 
146f56f2b3fSBarry Smith .seealso: MatDiagonalSet()
147052efed2SBarry Smith  @*/
148f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatShift(Mat Y,PetscScalar a)
149052efed2SBarry Smith {
1506849ba73SBarry Smith   PetscErrorCode ierr;
15138baddfdSBarry Smith   PetscInt       i,start,end;
152052efed2SBarry Smith 
1533a40ed3dSBarry Smith   PetscFunctionBegin;
1540700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
15517186662SBarry Smith   if (!Y->assembled) SETERRQ(((PetscObject)Y)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
15617186662SBarry Smith   if (Y->factortype) SETERRQ(((PetscObject)Y)->comm,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
157b50b34bdSBarry Smith   ierr = MatPreallocated(Y);CHKERRQ(ierr);
158b50b34bdSBarry Smith 
159f830108cSBarry Smith   if (Y->ops->shift) {
160f4df32b1SMatthew Knepley     ierr = (*Y->ops->shift)(Y,a);CHKERRQ(ierr);
16162d58ce1SBarry Smith   } else {
162f4df32b1SMatthew Knepley     PetscScalar alpha = a;
163d4bb536fSBarry Smith     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
164052efed2SBarry Smith     for (i=start; i<end; i++) {
165f4df32b1SMatthew Knepley       ierr = MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);CHKERRQ(ierr);
166052efed2SBarry Smith     }
1676d4a8577SBarry Smith     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1686d4a8577SBarry Smith     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
169052efed2SBarry Smith   }
1703a40ed3dSBarry Smith   PetscFunctionReturn(0);
171052efed2SBarry Smith }
1726d84be18SBarry Smith 
1734a2ae208SSatish Balay #undef __FUNCT__
17409f38230SBarry Smith #define __FUNCT__ "MatDiagonalSet_Default"
17509f38230SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet_Default(Mat Y,Vec D,InsertMode is)
17609f38230SBarry Smith {
17709f38230SBarry Smith   PetscErrorCode ierr;
17809f38230SBarry Smith   PetscInt       i,start,end,vstart,vend;
17909f38230SBarry Smith   PetscScalar    *v;
18009f38230SBarry Smith 
18109f38230SBarry Smith   PetscFunctionBegin;
18209f38230SBarry Smith   ierr = VecGetOwnershipRange(D,&vstart,&vend);CHKERRQ(ierr);
18309f38230SBarry Smith   ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
18409f38230SBarry Smith   if (vstart != start || vend != end) {
185e32f2f54SBarry Smith     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %D %D vec %D %D mat",vstart,vend,start,end);
18609f38230SBarry Smith   }
18709f38230SBarry Smith   ierr = VecGetArray(D,&v);CHKERRQ(ierr);
18809f38230SBarry Smith   for (i=start; i<end; i++) {
18909f38230SBarry Smith     ierr = MatSetValues(Y,1,&i,1,&i,v+i-start,is);CHKERRQ(ierr);
19009f38230SBarry Smith   }
19109f38230SBarry Smith   ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
19209f38230SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19309f38230SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19409f38230SBarry Smith   PetscFunctionReturn(0);
19509f38230SBarry Smith }
19609f38230SBarry Smith 
19709f38230SBarry Smith #undef __FUNCT__
1984a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalSet"
1996d84be18SBarry Smith /*@
200f56f2b3fSBarry Smith    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
201f56f2b3fSBarry Smith    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
202f56f2b3fSBarry Smith    INSERT_VALUES.
2036d84be18SBarry Smith 
2046d84be18SBarry Smith    Input Parameters:
20598a79cdbSBarry Smith +  Y - the input matrix
206f56f2b3fSBarry Smith .  D - the diagonal matrix, represented as a vector
207f56f2b3fSBarry Smith -  i - INSERT_VALUES or ADD_VALUES
2086d84be18SBarry Smith 
2093f9fe445SBarry Smith    Neighbor-wise Collective on Mat and Vec
210fee21e36SBarry Smith 
2112860a424SLois Curfman McInnes    Level: intermediate
2122860a424SLois Curfman McInnes 
2136b9ee512SLois Curfman McInnes .keywords: matrix, add, shift, diagonal
2146b9ee512SLois Curfman McInnes 
2156b9ee512SLois Curfman McInnes .seealso: MatShift()
2166d84be18SBarry Smith @*/
217be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet(Mat Y,Vec D,InsertMode is)
2186d84be18SBarry Smith {
2196849ba73SBarry Smith   PetscErrorCode ierr;
2206d84be18SBarry Smith 
2213a40ed3dSBarry Smith   PetscFunctionBegin;
2220700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
2230700a824SBarry Smith   PetscValidHeaderSpecific(D,VEC_CLASSID,2);
224f56f2b3fSBarry Smith   if (Y->ops->diagonalset) {
225f56f2b3fSBarry Smith     ierr = (*Y->ops->diagonalset)(Y,D,is);CHKERRQ(ierr);
22694d884c6SBarry Smith   } else {
22709f38230SBarry Smith     ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
2286d84be18SBarry Smith   }
2293a40ed3dSBarry Smith   PetscFunctionReturn(0);
2306d84be18SBarry Smith }
231d4bb536fSBarry Smith 
2324a2ae208SSatish Balay #undef __FUNCT__
2334a2ae208SSatish Balay #define __FUNCT__ "MatAYPX"
234d4bb536fSBarry Smith /*@
23504aac2b0SHong Zhang    MatAYPX - Computes Y = a*Y + X.
236d4bb536fSBarry Smith 
2373f9fe445SBarry Smith    Logically on Mat
238fee21e36SBarry Smith 
23998a79cdbSBarry Smith    Input Parameters:
24004aac2b0SHong Zhang +  a - the PetscScalar multiplier
24104aac2b0SHong Zhang .  Y - the first matrix
24204aac2b0SHong Zhang .  X - the second matrix
24304aac2b0SHong Zhang -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
244d4bb536fSBarry Smith 
2452860a424SLois Curfman McInnes    Notes:
24604aac2b0SHong Zhang      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
247607cd303SBarry Smith 
2482860a424SLois Curfman McInnes    Level: intermediate
2492860a424SLois Curfman McInnes 
250d4bb536fSBarry Smith .keywords: matrix, add
251d4bb536fSBarry Smith 
2522860a424SLois Curfman McInnes .seealso: MatAXPY()
253d4bb536fSBarry Smith  @*/
25404aac2b0SHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT MatAYPX(Mat Y,PetscScalar a,Mat X,MatStructure str)
255d4bb536fSBarry Smith {
25687828ca2SBarry Smith   PetscScalar    one = 1.0;
2576849ba73SBarry Smith   PetscErrorCode ierr;
25838baddfdSBarry Smith   PetscInt       mX,mY,nX,nY;
259d4bb536fSBarry Smith 
2603a40ed3dSBarry Smith   PetscFunctionBegin;
261c5eb9154SBarry Smith   PetscValidHeaderSpecific(X,MAT_CLASSID,3);
2620700a824SBarry Smith   PetscValidHeaderSpecific(Y,MAT_CLASSID,1);
263c5eb9154SBarry Smith   PetscValidLogicalCollectiveScalar(Y,a,2);
264329f5518SBarry Smith   ierr = MatGetSize(X,&mX,&nX);CHKERRQ(ierr);
265329f5518SBarry Smith   ierr = MatGetSize(X,&mY,&nY);CHKERRQ(ierr);
266e32f2f54SBarry 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);
267d4bb536fSBarry Smith 
268f4df32b1SMatthew Knepley   ierr = MatScale(Y,a);CHKERRQ(ierr);
269cb9801acSJed Brown   ierr = MatAXPY(Y,one,X,str);CHKERRQ(ierr);
2703a40ed3dSBarry Smith   PetscFunctionReturn(0);
271d4bb536fSBarry Smith }
272b0a32e0cSBarry Smith 
2734a2ae208SSatish Balay #undef __FUNCT__
2744a2ae208SSatish Balay #define __FUNCT__ "MatComputeExplicitOperator"
275b0a32e0cSBarry Smith /*@
276b0a32e0cSBarry Smith     MatComputeExplicitOperator - Computes the explicit matrix
277b0a32e0cSBarry Smith 
278b0a32e0cSBarry Smith     Collective on Mat
279b0a32e0cSBarry Smith 
280b0a32e0cSBarry Smith     Input Parameter:
281b0a32e0cSBarry Smith .   inmat - the matrix
282b0a32e0cSBarry Smith 
283b0a32e0cSBarry Smith     Output Parameter:
284b0a32e0cSBarry Smith .   mat - the explict preconditioned operator
285b0a32e0cSBarry Smith 
286b0a32e0cSBarry Smith     Notes:
287b0a32e0cSBarry Smith     This computation is done by applying the operators to columns of the
288b0a32e0cSBarry Smith     identity matrix.
289b0a32e0cSBarry Smith 
290b0a32e0cSBarry Smith     Currently, this routine uses a dense matrix format when 1 processor
291b0a32e0cSBarry Smith     is used and a sparse format otherwise.  This routine is costly in general,
292b0a32e0cSBarry Smith     and is recommended for use only with relatively small systems.
293b0a32e0cSBarry Smith 
294b0a32e0cSBarry Smith     Level: advanced
295b0a32e0cSBarry Smith 
296b0a32e0cSBarry Smith .keywords: Mat, compute, explicit, operator
297b0a32e0cSBarry Smith 
298b0a32e0cSBarry Smith @*/
299be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatComputeExplicitOperator(Mat inmat,Mat *mat)
300b0a32e0cSBarry Smith {
301b0a32e0cSBarry Smith   Vec            in,out;
302dfbe8321SBarry Smith   PetscErrorCode ierr;
3030b12b109SJed Brown   PetscInt       i,m,n,M,N,*rows,start,end;
304b0a32e0cSBarry Smith   MPI_Comm       comm;
30587828ca2SBarry Smith   PetscScalar    *array,zero = 0.0,one = 1.0;
30638baddfdSBarry Smith   PetscMPIInt    size;
307b0a32e0cSBarry Smith 
308b0a32e0cSBarry Smith   PetscFunctionBegin;
3090700a824SBarry Smith   PetscValidHeaderSpecific(inmat,MAT_CLASSID,1);
3104482741eSBarry Smith   PetscValidPointer(mat,2);
311b0a32e0cSBarry Smith 
3127adad957SLisandro Dalcin   comm = ((PetscObject)inmat)->comm;
313b0a32e0cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
314b0a32e0cSBarry Smith 
3150b12b109SJed Brown   ierr = MatGetLocalSize(inmat,&m,&n);CHKERRQ(ierr);
3160b12b109SJed Brown   ierr = MatGetSize(inmat,&M,&N);CHKERRQ(ierr);
3170b12b109SJed Brown   ierr = MatGetVecs(inmat,&in,&out);CHKERRQ(ierr);
3180b12b109SJed Brown   ierr = VecSetOption(in,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
3190b12b109SJed Brown   ierr = VecGetOwnershipRange(out,&start,&end);CHKERRQ(ierr);
3200b12b109SJed Brown   ierr = PetscMalloc(m*sizeof(PetscInt),&rows);CHKERRQ(ierr);
321b0a32e0cSBarry Smith   for (i=0; i<m; i++) {rows[i] = start + i;}
322b0a32e0cSBarry Smith 
323f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
3240b12b109SJed Brown   ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr);
325b0a32e0cSBarry Smith   if (size == 1) {
326be5d1d56SKris Buschelman     ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr);
327be5d1d56SKris Buschelman     ierr = MatSeqDenseSetPreallocation(*mat,PETSC_NULL);CHKERRQ(ierr);
328b0a32e0cSBarry Smith   } else {
329be5d1d56SKris Buschelman     ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
3300b12b109SJed Brown     ierr = MatMPIAIJSetPreallocation(*mat,n,PETSC_NULL,N-n,PETSC_NULL);CHKERRQ(ierr);
331b0a32e0cSBarry Smith   }
332b0a32e0cSBarry Smith 
3330b12b109SJed Brown   for (i=0; i<N; i++) {
334b0a32e0cSBarry Smith 
3352dcb1b2aSMatthew Knepley     ierr = VecSet(in,zero);CHKERRQ(ierr);
336b0a32e0cSBarry Smith     ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr);
337b0a32e0cSBarry Smith     ierr = VecAssemblyBegin(in);CHKERRQ(ierr);
338b0a32e0cSBarry Smith     ierr = VecAssemblyEnd(in);CHKERRQ(ierr);
339b0a32e0cSBarry Smith 
340b0a32e0cSBarry Smith     ierr = MatMult(inmat,in,out);CHKERRQ(ierr);
341b0a32e0cSBarry Smith 
342b0a32e0cSBarry Smith     ierr = VecGetArray(out,&array);CHKERRQ(ierr);
343b0a32e0cSBarry Smith     ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
344b0a32e0cSBarry Smith     ierr = VecRestoreArray(out,&array);CHKERRQ(ierr);
345b0a32e0cSBarry Smith 
346b0a32e0cSBarry Smith   }
347b0a32e0cSBarry Smith   ierr = PetscFree(rows);CHKERRQ(ierr);
348b0a32e0cSBarry Smith   ierr = VecDestroy(out);CHKERRQ(ierr);
349b0a32e0cSBarry Smith   ierr = VecDestroy(in);CHKERRQ(ierr);
350b0a32e0cSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
351b0a32e0cSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
352b0a32e0cSBarry Smith   PetscFunctionReturn(0);
353b0a32e0cSBarry Smith }
354b0a32e0cSBarry Smith 
35524f910e3SHong Zhang /* Get the map xtoy which is used by MatAXPY() in the case of SUBSET_NONZERO_PATTERN */
35624f910e3SHong Zhang #undef __FUNCT__
35724f910e3SHong Zhang #define __FUNCT__ "MatAXPYGetxtoy_Private"
35838baddfdSBarry Smith PetscErrorCode MatAXPYGetxtoy_Private(PetscInt m,PetscInt *xi,PetscInt *xj,PetscInt *xgarray, PetscInt *yi,PetscInt *yj,PetscInt *ygarray, PetscInt **xtoy)
35924f910e3SHong Zhang {
3606849ba73SBarry Smith   PetscErrorCode ierr;
36138baddfdSBarry Smith   PetscInt       row,i,nz,xcol,ycol,jx,jy,*x2y;
36224f910e3SHong Zhang 
36324f910e3SHong Zhang   PetscFunctionBegin;
36438baddfdSBarry Smith   ierr = PetscMalloc(xi[m]*sizeof(PetscInt),&x2y);CHKERRQ(ierr);
36524f910e3SHong Zhang   i = 0;
36624f910e3SHong Zhang   for (row=0; row<m; row++){
36724f910e3SHong Zhang     nz = xi[1] - xi[0];
36824f910e3SHong Zhang     jy = 0;
36924f910e3SHong Zhang     for (jx=0; jx<nz; jx++,jy++){
37024f910e3SHong Zhang       if (xgarray && ygarray){
37124f910e3SHong Zhang         xcol = xgarray[xj[*xi + jx]];
37224f910e3SHong Zhang         ycol = ygarray[yj[*yi + jy]];
37324f910e3SHong Zhang       } else {
37424f910e3SHong Zhang         xcol = xj[*xi + jx];
37524f910e3SHong Zhang         ycol = yj[*yi + jy];  /* col index for y */
37624f910e3SHong Zhang       }
37724f910e3SHong Zhang       while ( ycol < xcol ) {
37824f910e3SHong Zhang         jy++;
37924f910e3SHong Zhang         if (ygarray){
38024f910e3SHong Zhang           ycol = ygarray[yj[*yi + jy]];
38124f910e3SHong Zhang         } else {
38224f910e3SHong Zhang           ycol = yj[*yi + jy];
38324f910e3SHong Zhang         }
38424f910e3SHong Zhang       }
385e32f2f54SBarry Smith       if (xcol != ycol) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"X matrix entry (%D,%D) is not in Y matrix",row,ycol);
38624f910e3SHong Zhang       x2y[i++] = *yi + jy;
38724f910e3SHong Zhang     }
38824f910e3SHong Zhang     xi++; yi++;
38924f910e3SHong Zhang   }
39024f910e3SHong Zhang   *xtoy = x2y;
39124f910e3SHong Zhang   PetscFunctionReturn(0);
39224f910e3SHong Zhang }
393