xref: /petsc/src/mat/utils/axpy.c (revision 04aac2b00c46087e25aa2ce0e3dc7ce523ecb47e)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
26f79c3a4SBarry Smith 
3e090d566SSatish Balay #include "src/mat/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 
10fee21e36SBarry Smith    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
161a5ee19eSHong Zhang -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
1798a79cdbSBarry Smith 
182860a424SLois Curfman McInnes    Notes:
191a5ee19eSHong Zhang      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
202860a424SLois Curfman McInnes 
212860a424SLois Curfman McInnes    Level: intermediate
222860a424SLois Curfman McInnes 
239cf4f1e8SLois Curfman McInnes .keywords: matrix, add
24d4bb536fSBarry Smith 
252860a424SLois Curfman McInnes .seealso: MatAYPX()
2606be10caSBarry Smith  @*/
27f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str)
286f79c3a4SBarry Smith {
296849ba73SBarry Smith   PetscErrorCode ierr;
30c1ac3661SBarry Smith   PetscInt       m1,m2,n1,n2;
316f79c3a4SBarry Smith 
323a40ed3dSBarry Smith   PetscFunctionBegin;
33f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(X,MAT_COOKIE,3);
34f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
3590f02eecSBarry Smith 
36273d9f13SBarry Smith   ierr = MatGetSize(X,&m1,&n1);CHKERRQ(ierr);
37273d9f13SBarry Smith   ierr = MatGetSize(Y,&m2,&n2);CHKERRQ(ierr);
3877431f27SBarry Smith   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %D %D %D %D",m1,m2,n1,n2);
391987afe7SBarry Smith 
40f4df32b1SMatthew Knepley   if (Y->ops->axpy) {
41f4df32b1SMatthew Knepley     ierr = (*Y->ops->axpy)(Y,a,X,str);CHKERRQ(ierr);
42d4bb536fSBarry Smith   } else {
43f4df32b1SMatthew Knepley     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
44607cd303SBarry Smith   }
45607cd303SBarry Smith   PetscFunctionReturn(0);
46607cd303SBarry Smith }
47607cd303SBarry Smith 
48607cd303SBarry Smith 
49607cd303SBarry Smith #undef __FUNCT__
50607cd303SBarry Smith #define __FUNCT__ "MatAXPY_Basic"
51f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_Basic(Mat Y,PetscScalar a,Mat X,MatStructure str)
52607cd303SBarry Smith {
5338baddfdSBarry Smith   PetscInt          i,start,end,j,ncols,m,n;
546849ba73SBarry Smith   PetscErrorCode    ierr;
5538baddfdSBarry Smith   const PetscInt    *row;
56b3cc6726SBarry Smith   PetscScalar       *val;
57b3cc6726SBarry Smith   const PetscScalar *vals;
58607cd303SBarry Smith 
59607cd303SBarry Smith   PetscFunctionBegin;
608dadbd76SSatish Balay   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
6190f02eecSBarry Smith   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
62f4df32b1SMatthew Knepley   if (a == 1.0) {
63d4bb536fSBarry Smith     for (i = start; i < end; i++) {
64d4bb536fSBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
65d4bb536fSBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
66d4bb536fSBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
67d4bb536fSBarry Smith     }
68d4bb536fSBarry Smith   } else {
69b3cc6726SBarry Smith     ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&val);CHKERRQ(ierr);
7006be10caSBarry Smith     for (i=start; i<end; i++) {
71b3cc6726SBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
7206be10caSBarry Smith       for (j=0; j<ncols; j++) {
73f4df32b1SMatthew Knepley 	val[j] = a*vals[j];
746f79c3a4SBarry Smith       }
75b3cc6726SBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,val,ADD_VALUES);CHKERRQ(ierr);
76b3cc6726SBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
776f79c3a4SBarry Smith     }
78b3cc6726SBarry Smith     ierr = PetscFree(val);CHKERRQ(ierr);
79d4bb536fSBarry Smith   }
806d4a8577SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
816d4a8577SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
823a40ed3dSBarry Smith   PetscFunctionReturn(0);
836f79c3a4SBarry Smith }
84052efed2SBarry Smith 
854a2ae208SSatish Balay #undef __FUNCT__
864a2ae208SSatish Balay #define __FUNCT__ "MatShift"
87052efed2SBarry Smith /*@
8887828ca2SBarry Smith    MatShift - Computes Y =  Y + a I, where a is a PetscScalar and I is the identity matrix.
89052efed2SBarry Smith 
90fee21e36SBarry Smith    Collective on Mat
91fee21e36SBarry Smith 
9298a79cdbSBarry Smith    Input Parameters:
9398a79cdbSBarry Smith +  Y - the matrices
9487828ca2SBarry Smith -  a - the PetscScalar
9598a79cdbSBarry Smith 
962860a424SLois Curfman McInnes    Level: intermediate
972860a424SLois Curfman McInnes 
98052efed2SBarry Smith .keywords: matrix, add, shift
996b9ee512SLois Curfman McInnes 
100f56f2b3fSBarry Smith .seealso: MatDiagonalSet()
101052efed2SBarry Smith  @*/
102f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatShift(Mat Y,PetscScalar a)
103052efed2SBarry Smith {
1046849ba73SBarry Smith   PetscErrorCode ierr;
10538baddfdSBarry Smith   PetscInt       i,start,end;
106052efed2SBarry Smith 
1073a40ed3dSBarry Smith   PetscFunctionBegin;
108f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
10932dfb669SBarry Smith   if (!Y->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
11032dfb669SBarry Smith   if (Y->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
111b50b34bdSBarry Smith   ierr = MatPreallocated(Y);CHKERRQ(ierr);
112b50b34bdSBarry Smith 
113f830108cSBarry Smith   if (Y->ops->shift) {
114f4df32b1SMatthew Knepley     ierr = (*Y->ops->shift)(Y,a);CHKERRQ(ierr);
11562d58ce1SBarry Smith   } else {
116f4df32b1SMatthew Knepley     PetscScalar alpha = a;
117d4bb536fSBarry Smith     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
118052efed2SBarry Smith     for (i=start; i<end; i++) {
119f4df32b1SMatthew Knepley       ierr = MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);CHKERRQ(ierr);
120052efed2SBarry Smith     }
1216d4a8577SBarry Smith     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1226d4a8577SBarry Smith     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
123052efed2SBarry Smith   }
1243a40ed3dSBarry Smith   PetscFunctionReturn(0);
125052efed2SBarry Smith }
1266d84be18SBarry Smith 
1274a2ae208SSatish Balay #undef __FUNCT__
12809f38230SBarry Smith #define __FUNCT__ "MatDiagonalSet_Default"
12909f38230SBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet_Default(Mat Y,Vec D,InsertMode is)
13009f38230SBarry Smith {
13109f38230SBarry Smith   PetscErrorCode ierr;
13209f38230SBarry Smith   PetscInt       i,start,end,vstart,vend;
13309f38230SBarry Smith   PetscScalar    *v;
13409f38230SBarry Smith 
13509f38230SBarry Smith   PetscFunctionBegin;
13609f38230SBarry Smith   ierr = VecGetOwnershipRange(D,&vstart,&vend);CHKERRQ(ierr);
13709f38230SBarry Smith   ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
13809f38230SBarry Smith   if (vstart != start || vend != end) {
13909f38230SBarry Smith     SETERRQ4(PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %D %D vec %D %D mat",vstart,vend,start,end);
14009f38230SBarry Smith   }
14109f38230SBarry Smith   ierr = VecGetArray(D,&v);CHKERRQ(ierr);
14209f38230SBarry Smith   for (i=start; i<end; i++) {
14309f38230SBarry Smith     ierr = MatSetValues(Y,1,&i,1,&i,v+i-start,is);CHKERRQ(ierr);
14409f38230SBarry Smith   }
14509f38230SBarry Smith   ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
14609f38230SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14709f38230SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14809f38230SBarry Smith   PetscFunctionReturn(0);
14909f38230SBarry Smith }
15009f38230SBarry Smith 
15109f38230SBarry Smith #undef __FUNCT__
1524a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalSet"
1536d84be18SBarry Smith /*@
154f56f2b3fSBarry Smith    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
155f56f2b3fSBarry Smith    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
156f56f2b3fSBarry Smith    INSERT_VALUES.
1576d84be18SBarry Smith 
1586d84be18SBarry Smith    Input Parameters:
15998a79cdbSBarry Smith +  Y - the input matrix
160f56f2b3fSBarry Smith .  D - the diagonal matrix, represented as a vector
161f56f2b3fSBarry Smith -  i - INSERT_VALUES or ADD_VALUES
1626d84be18SBarry Smith 
163fee21e36SBarry Smith    Collective on Mat and Vec
164fee21e36SBarry Smith 
1652860a424SLois Curfman McInnes    Level: intermediate
1662860a424SLois Curfman McInnes 
1676b9ee512SLois Curfman McInnes .keywords: matrix, add, shift, diagonal
1686b9ee512SLois Curfman McInnes 
1696b9ee512SLois Curfman McInnes .seealso: MatShift()
1706d84be18SBarry Smith @*/
171be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet(Mat Y,Vec D,InsertMode is)
1726d84be18SBarry Smith {
1736849ba73SBarry Smith   PetscErrorCode ierr;
1746d84be18SBarry Smith 
1753a40ed3dSBarry Smith   PetscFunctionBegin;
1764482741eSBarry Smith   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
1774482741eSBarry Smith   PetscValidHeaderSpecific(D,VEC_COOKIE,2);
178f56f2b3fSBarry Smith   if (Y->ops->diagonalset) {
179f56f2b3fSBarry Smith     ierr = (*Y->ops->diagonalset)(Y,D,is);CHKERRQ(ierr);
18094d884c6SBarry Smith   } else {
18109f38230SBarry Smith     ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
1826d84be18SBarry Smith   }
1833a40ed3dSBarry Smith   PetscFunctionReturn(0);
1846d84be18SBarry Smith }
185d4bb536fSBarry Smith 
1864a2ae208SSatish Balay #undef __FUNCT__
1874a2ae208SSatish Balay #define __FUNCT__ "MatAYPX"
188d4bb536fSBarry Smith /*@
189*04aac2b0SHong Zhang    MatAYPX - Computes Y = a*Y + X.
190d4bb536fSBarry Smith 
191fee21e36SBarry Smith    Collective on Mat
192fee21e36SBarry Smith 
19398a79cdbSBarry Smith    Input Parameters:
194*04aac2b0SHong Zhang +  a - the PetscScalar multiplier
195*04aac2b0SHong Zhang .  Y - the first matrix
196*04aac2b0SHong Zhang .  X - the second matrix
197*04aac2b0SHong Zhang -  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
198d4bb536fSBarry Smith 
1992860a424SLois Curfman McInnes    Notes:
200*04aac2b0SHong Zhang      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
201607cd303SBarry Smith 
2022860a424SLois Curfman McInnes    Level: intermediate
2032860a424SLois Curfman McInnes 
204d4bb536fSBarry Smith .keywords: matrix, add
205d4bb536fSBarry Smith 
2062860a424SLois Curfman McInnes .seealso: MatAXPY()
207d4bb536fSBarry Smith  @*/
208*04aac2b0SHong Zhang PetscErrorCode PETSCMAT_DLLEXPORT MatAYPX(Mat Y,PetscScalar a,Mat X,MatStructure str)
209d4bb536fSBarry Smith {
21087828ca2SBarry Smith   PetscScalar    one = 1.0;
2116849ba73SBarry Smith   PetscErrorCode ierr;
21238baddfdSBarry Smith   PetscInt       mX,mY,nX,nY;
213d4bb536fSBarry Smith 
2143a40ed3dSBarry Smith   PetscFunctionBegin;
2154482741eSBarry Smith   PetscValidHeaderSpecific(X,MAT_COOKIE,2);
216f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
217d4bb536fSBarry Smith 
218329f5518SBarry Smith   ierr = MatGetSize(X,&mX,&nX);CHKERRQ(ierr);
219329f5518SBarry Smith   ierr = MatGetSize(X,&mY,&nY);CHKERRQ(ierr);
22077431f27SBarry Smith   if (mX != mY || nX != nY) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrices: %D %D first %D %D second",mX,mY,nX,nY);
221d4bb536fSBarry Smith 
222f4df32b1SMatthew Knepley   ierr = MatScale(Y,a);CHKERRQ(ierr);
223*04aac2b0SHong Zhang   ierr = MatAXPY(Y,one,X,str);CHKERRQ(ierr)
2243a40ed3dSBarry Smith   PetscFunctionReturn(0);
225d4bb536fSBarry Smith }
226b0a32e0cSBarry Smith 
2274a2ae208SSatish Balay #undef __FUNCT__
2284a2ae208SSatish Balay #define __FUNCT__ "MatComputeExplicitOperator"
229b0a32e0cSBarry Smith /*@
230b0a32e0cSBarry Smith     MatComputeExplicitOperator - Computes the explicit matrix
231b0a32e0cSBarry Smith 
232b0a32e0cSBarry Smith     Collective on Mat
233b0a32e0cSBarry Smith 
234b0a32e0cSBarry Smith     Input Parameter:
235b0a32e0cSBarry Smith .   inmat - the matrix
236b0a32e0cSBarry Smith 
237b0a32e0cSBarry Smith     Output Parameter:
238b0a32e0cSBarry Smith .   mat - the explict preconditioned operator
239b0a32e0cSBarry Smith 
240b0a32e0cSBarry Smith     Notes:
241b0a32e0cSBarry Smith     This computation is done by applying the operators to columns of the
242b0a32e0cSBarry Smith     identity matrix.
243b0a32e0cSBarry Smith 
244b0a32e0cSBarry Smith     Currently, this routine uses a dense matrix format when 1 processor
245b0a32e0cSBarry Smith     is used and a sparse format otherwise.  This routine is costly in general,
246b0a32e0cSBarry Smith     and is recommended for use only with relatively small systems.
247b0a32e0cSBarry Smith 
248b0a32e0cSBarry Smith     Level: advanced
249b0a32e0cSBarry Smith 
250b0a32e0cSBarry Smith .keywords: Mat, compute, explicit, operator
251b0a32e0cSBarry Smith 
252b0a32e0cSBarry Smith @*/
253be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatComputeExplicitOperator(Mat inmat,Mat *mat)
254b0a32e0cSBarry Smith {
255b0a32e0cSBarry Smith   Vec            in,out;
256dfbe8321SBarry Smith   PetscErrorCode ierr;
25738baddfdSBarry Smith   PetscInt       i,M,m,*rows,start,end;
258b0a32e0cSBarry Smith   MPI_Comm       comm;
25987828ca2SBarry Smith   PetscScalar    *array,zero = 0.0,one = 1.0;
26038baddfdSBarry Smith   PetscMPIInt    size;
261b0a32e0cSBarry Smith 
262b0a32e0cSBarry Smith   PetscFunctionBegin;
2634482741eSBarry Smith   PetscValidHeaderSpecific(inmat,MAT_COOKIE,1);
2644482741eSBarry Smith   PetscValidPointer(mat,2);
265b0a32e0cSBarry Smith 
266b0a32e0cSBarry Smith   comm = inmat->comm;
267b0a32e0cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
268b0a32e0cSBarry Smith 
269b22afee1SSatish Balay   ierr = MatGetLocalSize(inmat,&m,0);CHKERRQ(ierr);
270b22afee1SSatish Balay   ierr = MatGetSize(inmat,&M,0);CHKERRQ(ierr);
271b0a32e0cSBarry Smith   ierr = VecCreateMPI(comm,m,M,&in);CHKERRQ(ierr);
272b0a32e0cSBarry Smith   ierr = VecDuplicate(in,&out);CHKERRQ(ierr);
273b0a32e0cSBarry Smith   ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr);
27438baddfdSBarry Smith   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&rows);CHKERRQ(ierr);
275b0a32e0cSBarry Smith   for (i=0; i<m; i++) {rows[i] = start + i;}
276b0a32e0cSBarry Smith 
277f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
278f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,m,M,M);CHKERRQ(ierr);
279b0a32e0cSBarry Smith   if (size == 1) {
280be5d1d56SKris Buschelman     ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr);
281be5d1d56SKris Buschelman     ierr = MatSeqDenseSetPreallocation(*mat,PETSC_NULL);CHKERRQ(ierr);
282b0a32e0cSBarry Smith   } else {
283be5d1d56SKris Buschelman     ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
284be5d1d56SKris Buschelman     ierr = MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
285b0a32e0cSBarry Smith   }
286b0a32e0cSBarry Smith 
287b0a32e0cSBarry Smith   for (i=0; i<M; i++) {
288b0a32e0cSBarry Smith 
2892dcb1b2aSMatthew Knepley     ierr = VecSet(in,zero);CHKERRQ(ierr);
290b0a32e0cSBarry Smith     ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr);
291b0a32e0cSBarry Smith     ierr = VecAssemblyBegin(in);CHKERRQ(ierr);
292b0a32e0cSBarry Smith     ierr = VecAssemblyEnd(in);CHKERRQ(ierr);
293b0a32e0cSBarry Smith 
294b0a32e0cSBarry Smith     ierr = MatMult(inmat,in,out);CHKERRQ(ierr);
295b0a32e0cSBarry Smith 
296b0a32e0cSBarry Smith     ierr = VecGetArray(out,&array);CHKERRQ(ierr);
297b0a32e0cSBarry Smith     ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
298b0a32e0cSBarry Smith     ierr = VecRestoreArray(out,&array);CHKERRQ(ierr);
299b0a32e0cSBarry Smith 
300b0a32e0cSBarry Smith   }
301b0a32e0cSBarry Smith   ierr = PetscFree(rows);CHKERRQ(ierr);
302b0a32e0cSBarry Smith   ierr = VecDestroy(out);CHKERRQ(ierr);
303b0a32e0cSBarry Smith   ierr = VecDestroy(in);CHKERRQ(ierr);
304b0a32e0cSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
305b0a32e0cSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
306b0a32e0cSBarry Smith   PetscFunctionReturn(0);
307b0a32e0cSBarry Smith }
308b0a32e0cSBarry Smith 
30924f910e3SHong Zhang /* Get the map xtoy which is used by MatAXPY() in the case of SUBSET_NONZERO_PATTERN */
31024f910e3SHong Zhang #undef __FUNCT__
31124f910e3SHong Zhang #define __FUNCT__ "MatAXPYGetxtoy_Private"
31238baddfdSBarry Smith PetscErrorCode MatAXPYGetxtoy_Private(PetscInt m,PetscInt *xi,PetscInt *xj,PetscInt *xgarray, PetscInt *yi,PetscInt *yj,PetscInt *ygarray, PetscInt **xtoy)
31324f910e3SHong Zhang {
3146849ba73SBarry Smith   PetscErrorCode ierr;
31538baddfdSBarry Smith   PetscInt       row,i,nz,xcol,ycol,jx,jy,*x2y;
31624f910e3SHong Zhang 
31724f910e3SHong Zhang   PetscFunctionBegin;
31838baddfdSBarry Smith   ierr = PetscMalloc(xi[m]*sizeof(PetscInt),&x2y);CHKERRQ(ierr);
31924f910e3SHong Zhang   i = 0;
32024f910e3SHong Zhang   for (row=0; row<m; row++){
32124f910e3SHong Zhang     nz = xi[1] - xi[0];
32224f910e3SHong Zhang     jy = 0;
32324f910e3SHong Zhang     for (jx=0; jx<nz; jx++,jy++){
32424f910e3SHong Zhang       if (xgarray && ygarray){
32524f910e3SHong Zhang         xcol = xgarray[xj[*xi + jx]];
32624f910e3SHong Zhang         ycol = ygarray[yj[*yi + jy]];
32724f910e3SHong Zhang       } else {
32824f910e3SHong Zhang         xcol = xj[*xi + jx];
32924f910e3SHong Zhang         ycol = yj[*yi + jy];  /* col index for y */
33024f910e3SHong Zhang       }
33124f910e3SHong Zhang       while ( ycol < xcol ) {
33224f910e3SHong Zhang         jy++;
33324f910e3SHong Zhang         if (ygarray){
33424f910e3SHong Zhang           ycol = ygarray[yj[*yi + jy]];
33524f910e3SHong Zhang         } else {
33624f910e3SHong Zhang           ycol = yj[*yi + jy];
33724f910e3SHong Zhang         }
33824f910e3SHong Zhang       }
33977431f27SBarry Smith       if (xcol != ycol) SETERRQ2(PETSC_ERR_ARG_WRONG,"X matrix entry (%D,%D) is not in Y matrix",row,ycol);
34024f910e3SHong Zhang       x2y[i++] = *yi + jy;
34124f910e3SHong Zhang     }
34224f910e3SHong Zhang     xi++; yi++;
34324f910e3SHong Zhang   }
34424f910e3SHong Zhang   *xtoy = x2y;
34524f910e3SHong Zhang   PetscFunctionReturn(0);
34624f910e3SHong Zhang }
347