xref: /petsc/src/mat/utils/axpy.c (revision f4df32b132e30afc79b77d8c3179eb18c28a5b40)
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 
18e182c471SBarry Smith    Contributed by: Matthew Knepley
19d4bb536fSBarry Smith 
202860a424SLois Curfman McInnes    Notes:
211a5ee19eSHong Zhang      Will only be efficient if one has the SAME_NONZERO_PATTERN or SUBSET_NONZERO_PATTERN
222860a424SLois Curfman McInnes 
232860a424SLois Curfman McInnes    Level: intermediate
242860a424SLois Curfman McInnes 
259cf4f1e8SLois Curfman McInnes .keywords: matrix, add
26d4bb536fSBarry Smith 
272860a424SLois Curfman McInnes .seealso: MatAYPX()
2806be10caSBarry Smith  @*/
29*f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str)
306f79c3a4SBarry Smith {
316849ba73SBarry Smith   PetscErrorCode ierr;
32c1ac3661SBarry Smith   PetscInt       m1,m2,n1,n2;
336f79c3a4SBarry Smith 
343a40ed3dSBarry Smith   PetscFunctionBegin;
354482741eSBarry Smith   PetscValidScalarPointer(a,1);
36*f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(X,MAT_COOKIE,3);
37*f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
3890f02eecSBarry Smith 
39273d9f13SBarry Smith   ierr = MatGetSize(X,&m1,&n1);CHKERRQ(ierr);
40273d9f13SBarry Smith   ierr = MatGetSize(Y,&m2,&n2);CHKERRQ(ierr);
4177431f27SBarry Smith   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrix add: %D %D %D %D",m1,m2,n1,n2);
421987afe7SBarry Smith 
43*f4df32b1SMatthew Knepley   if (Y->ops->axpy) {
44*f4df32b1SMatthew Knepley     ierr = (*Y->ops->axpy)(Y,a,X,str);CHKERRQ(ierr);
45d4bb536fSBarry Smith   } else {
46*f4df32b1SMatthew Knepley     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
47607cd303SBarry Smith   }
48607cd303SBarry Smith   PetscFunctionReturn(0);
49607cd303SBarry Smith }
50607cd303SBarry Smith 
51607cd303SBarry Smith 
52607cd303SBarry Smith #undef __FUNCT__
53607cd303SBarry Smith #define __FUNCT__ "MatAXPY_Basic"
54*f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_Basic(Mat Y,PetscScalar a,Mat X,MatStructure str)
55607cd303SBarry Smith {
5638baddfdSBarry Smith   PetscInt          i,start,end,j,ncols,m,n;
576849ba73SBarry Smith   PetscErrorCode    ierr;
5838baddfdSBarry Smith   const PetscInt    *row;
59b3cc6726SBarry Smith   PetscScalar       *val;
60b3cc6726SBarry Smith   const PetscScalar *vals;
61607cd303SBarry Smith 
62607cd303SBarry Smith   PetscFunctionBegin;
638dadbd76SSatish Balay   ierr = MatGetSize(X,&m,&n);CHKERRQ(ierr);
6490f02eecSBarry Smith   ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
65*f4df32b1SMatthew Knepley   if (a == 1.0) {
66d4bb536fSBarry Smith     for (i = start; i < end; i++) {
67d4bb536fSBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
68d4bb536fSBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
69d4bb536fSBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
70d4bb536fSBarry Smith     }
71d4bb536fSBarry Smith   } else {
72b3cc6726SBarry Smith     ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&val);CHKERRQ(ierr);
7306be10caSBarry Smith     for (i=start; i<end; i++) {
74b3cc6726SBarry Smith       ierr = MatGetRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
7506be10caSBarry Smith       for (j=0; j<ncols; j++) {
76*f4df32b1SMatthew Knepley 	val[j] = a*vals[j];
776f79c3a4SBarry Smith       }
78b3cc6726SBarry Smith       ierr = MatSetValues(Y,1,&i,ncols,row,val,ADD_VALUES);CHKERRQ(ierr);
79b3cc6726SBarry Smith       ierr = MatRestoreRow(X,i,&ncols,&row,&vals);CHKERRQ(ierr);
806f79c3a4SBarry Smith     }
81b3cc6726SBarry Smith     ierr = PetscFree(val);CHKERRQ(ierr);
82d4bb536fSBarry Smith   }
836d4a8577SBarry Smith   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
846d4a8577SBarry Smith   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
853a40ed3dSBarry Smith   PetscFunctionReturn(0);
866f79c3a4SBarry Smith }
87052efed2SBarry Smith 
884a2ae208SSatish Balay #undef __FUNCT__
894a2ae208SSatish Balay #define __FUNCT__ "MatShift"
90052efed2SBarry Smith /*@
9187828ca2SBarry Smith    MatShift - Computes Y =  Y + a I, where a is a PetscScalar and I is the identity matrix.
92052efed2SBarry Smith 
93fee21e36SBarry Smith    Collective on Mat
94fee21e36SBarry Smith 
9598a79cdbSBarry Smith    Input Parameters:
9698a79cdbSBarry Smith +  Y - the matrices
9787828ca2SBarry Smith -  a - the PetscScalar
9898a79cdbSBarry Smith 
992860a424SLois Curfman McInnes    Level: intermediate
1002860a424SLois Curfman McInnes 
101052efed2SBarry Smith .keywords: matrix, add, shift
1026b9ee512SLois Curfman McInnes 
103f56f2b3fSBarry Smith .seealso: MatDiagonalSet()
104052efed2SBarry Smith  @*/
105*f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatShift(Mat Y,PetscScalar a)
106052efed2SBarry Smith {
1076849ba73SBarry Smith   PetscErrorCode ierr;
10838baddfdSBarry Smith   PetscInt       i,start,end;
109052efed2SBarry Smith 
1103a40ed3dSBarry Smith   PetscFunctionBegin;
111*f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
11232dfb669SBarry Smith   if (!Y->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
11332dfb669SBarry Smith   if (Y->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
114b50b34bdSBarry Smith   ierr = MatPreallocated(Y);CHKERRQ(ierr);
115b50b34bdSBarry Smith 
116f830108cSBarry Smith   if (Y->ops->shift) {
117*f4df32b1SMatthew Knepley     ierr = (*Y->ops->shift)(Y,a);CHKERRQ(ierr);
11862d58ce1SBarry Smith   } else {
119*f4df32b1SMatthew Knepley     PetscScalar alpha = a;
120d4bb536fSBarry Smith     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
121052efed2SBarry Smith     for (i=start; i<end; i++) {
122*f4df32b1SMatthew Knepley       ierr = MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);CHKERRQ(ierr);
123052efed2SBarry Smith     }
1246d4a8577SBarry Smith     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1256d4a8577SBarry Smith     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
126052efed2SBarry Smith   }
1273a40ed3dSBarry Smith   PetscFunctionReturn(0);
128052efed2SBarry Smith }
1296d84be18SBarry Smith 
1304a2ae208SSatish Balay #undef __FUNCT__
1314a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalSet"
1326d84be18SBarry Smith /*@
133f56f2b3fSBarry Smith    MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix
134f56f2b3fSBarry Smith    that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is
135f56f2b3fSBarry Smith    INSERT_VALUES.
1366d84be18SBarry Smith 
1376d84be18SBarry Smith    Input Parameters:
13898a79cdbSBarry Smith +  Y - the input matrix
139f56f2b3fSBarry Smith .  D - the diagonal matrix, represented as a vector
140f56f2b3fSBarry Smith -  i - INSERT_VALUES or ADD_VALUES
1416d84be18SBarry Smith 
142fee21e36SBarry Smith    Collective on Mat and Vec
143fee21e36SBarry Smith 
1442860a424SLois Curfman McInnes    Level: intermediate
1452860a424SLois Curfman McInnes 
1466b9ee512SLois Curfman McInnes .keywords: matrix, add, shift, diagonal
1476b9ee512SLois Curfman McInnes 
1486b9ee512SLois Curfman McInnes .seealso: MatShift()
1496d84be18SBarry Smith @*/
150be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet(Mat Y,Vec D,InsertMode is)
1516d84be18SBarry Smith {
1526849ba73SBarry Smith   PetscErrorCode ierr;
15338baddfdSBarry Smith   PetscInt       i,start,end;
1546d84be18SBarry Smith 
1553a40ed3dSBarry Smith   PetscFunctionBegin;
1564482741eSBarry Smith   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
1574482741eSBarry Smith   PetscValidHeaderSpecific(D,VEC_COOKIE,2);
158f56f2b3fSBarry Smith   if (Y->ops->diagonalset) {
159f56f2b3fSBarry Smith     ierr = (*Y->ops->diagonalset)(Y,D,is);CHKERRQ(ierr);
16094d884c6SBarry Smith   } else {
16138baddfdSBarry Smith     PetscInt    vstart,vend;
16287828ca2SBarry Smith     PetscScalar *v;
1636d84be18SBarry Smith     ierr = VecGetOwnershipRange(D,&vstart,&vend);CHKERRQ(ierr);
1646d84be18SBarry Smith     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
165d4bb536fSBarry Smith     if (vstart != start || vend != end) {
16677431f27SBarry Smith       SETERRQ4(PETSC_ERR_ARG_SIZ,"Vector ownership range not compatible with matrix: %D %D vec %D %D mat",vstart,vend,start,end);
167d4bb536fSBarry Smith     }
1686d84be18SBarry Smith     ierr = VecGetArray(D,&v);CHKERRQ(ierr);
1696d84be18SBarry Smith     for (i=start; i<end; i++) {
170f56f2b3fSBarry Smith       ierr = MatSetValues(Y,1,&i,1,&i,v+i-start,is);CHKERRQ(ierr);
1716d84be18SBarry Smith     }
1722e8a6d31SBarry Smith     ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
1736d4a8577SBarry Smith     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1746d4a8577SBarry Smith     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1756d84be18SBarry Smith   }
1763a40ed3dSBarry Smith   PetscFunctionReturn(0);
1776d84be18SBarry Smith }
178d4bb536fSBarry Smith 
1794a2ae208SSatish Balay #undef __FUNCT__
1804a2ae208SSatish Balay #define __FUNCT__ "MatAYPX"
181d4bb536fSBarry Smith /*@
182d4bb536fSBarry Smith    MatAYPX - Computes Y = X + a*Y.
183d4bb536fSBarry Smith 
184fee21e36SBarry Smith    Collective on Mat
185fee21e36SBarry Smith 
18698a79cdbSBarry Smith    Input Parameters:
18798a79cdbSBarry Smith +  X,Y - the matrices
18887828ca2SBarry Smith -  a - the PetscScalar multiplier
18998a79cdbSBarry Smith 
190e182c471SBarry Smith    Contributed by: Matthew Knepley
191d4bb536fSBarry Smith 
1922860a424SLois Curfman McInnes    Notes:
1932860a424SLois Curfman McInnes    This routine currently uses the MatAXPY() implementation.
1942860a424SLois Curfman McInnes 
195607cd303SBarry Smith    This is slow, if you need it fast send email to petsc-maint@mcs.anl.gov
196607cd303SBarry Smith 
1972860a424SLois Curfman McInnes    Level: intermediate
1982860a424SLois Curfman McInnes 
199d4bb536fSBarry Smith .keywords: matrix, add
200d4bb536fSBarry Smith 
2012860a424SLois Curfman McInnes .seealso: MatAXPY()
202d4bb536fSBarry Smith  @*/
203*f4df32b1SMatthew Knepley PetscErrorCode PETSCMAT_DLLEXPORT MatAYPX(Mat Y,PetscScalar a,Mat X)
204d4bb536fSBarry Smith {
20587828ca2SBarry Smith   PetscScalar    one = 1.0;
2066849ba73SBarry Smith   PetscErrorCode ierr;
20738baddfdSBarry Smith   PetscInt       mX,mY,nX,nY;
208d4bb536fSBarry Smith 
2093a40ed3dSBarry Smith   PetscFunctionBegin;
2104482741eSBarry Smith   PetscValidHeaderSpecific(X,MAT_COOKIE,2);
211*f4df32b1SMatthew Knepley   PetscValidHeaderSpecific(Y,MAT_COOKIE,1);
212d4bb536fSBarry Smith 
213329f5518SBarry Smith   ierr = MatGetSize(X,&mX,&nX);CHKERRQ(ierr);
214329f5518SBarry Smith   ierr = MatGetSize(X,&mY,&nY);CHKERRQ(ierr);
21577431f27SBarry Smith   if (mX != mY || nX != nY) SETERRQ4(PETSC_ERR_ARG_SIZ,"Non conforming matrices: %D %D first %D %D second",mX,mY,nX,nY);
216d4bb536fSBarry Smith 
217*f4df32b1SMatthew Knepley   ierr = MatScale(Y,a);CHKERRQ(ierr);
218*f4df32b1SMatthew Knepley   ierr = MatAXPY(Y,one,X,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2193a40ed3dSBarry Smith   PetscFunctionReturn(0);
220d4bb536fSBarry Smith }
221b0a32e0cSBarry Smith 
2224a2ae208SSatish Balay #undef __FUNCT__
2234a2ae208SSatish Balay #define __FUNCT__ "MatComputeExplicitOperator"
224b0a32e0cSBarry Smith /*@
225b0a32e0cSBarry Smith     MatComputeExplicitOperator - Computes the explicit matrix
226b0a32e0cSBarry Smith 
227b0a32e0cSBarry Smith     Collective on Mat
228b0a32e0cSBarry Smith 
229b0a32e0cSBarry Smith     Input Parameter:
230b0a32e0cSBarry Smith .   inmat - the matrix
231b0a32e0cSBarry Smith 
232b0a32e0cSBarry Smith     Output Parameter:
233b0a32e0cSBarry Smith .   mat - the explict preconditioned operator
234b0a32e0cSBarry Smith 
235b0a32e0cSBarry Smith     Notes:
236b0a32e0cSBarry Smith     This computation is done by applying the operators to columns of the
237b0a32e0cSBarry Smith     identity matrix.
238b0a32e0cSBarry Smith 
239b0a32e0cSBarry Smith     Currently, this routine uses a dense matrix format when 1 processor
240b0a32e0cSBarry Smith     is used and a sparse format otherwise.  This routine is costly in general,
241b0a32e0cSBarry Smith     and is recommended for use only with relatively small systems.
242b0a32e0cSBarry Smith 
243b0a32e0cSBarry Smith     Level: advanced
244b0a32e0cSBarry Smith 
245b0a32e0cSBarry Smith .keywords: Mat, compute, explicit, operator
246b0a32e0cSBarry Smith 
247b0a32e0cSBarry Smith @*/
248be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatComputeExplicitOperator(Mat inmat,Mat *mat)
249b0a32e0cSBarry Smith {
250b0a32e0cSBarry Smith   Vec            in,out;
251dfbe8321SBarry Smith   PetscErrorCode ierr;
25238baddfdSBarry Smith   PetscInt       i,M,m,*rows,start,end;
253b0a32e0cSBarry Smith   MPI_Comm       comm;
25487828ca2SBarry Smith   PetscScalar    *array,zero = 0.0,one = 1.0;
25538baddfdSBarry Smith   PetscMPIInt    size;
256b0a32e0cSBarry Smith 
257b0a32e0cSBarry Smith   PetscFunctionBegin;
2584482741eSBarry Smith   PetscValidHeaderSpecific(inmat,MAT_COOKIE,1);
2594482741eSBarry Smith   PetscValidPointer(mat,2);
260b0a32e0cSBarry Smith 
261b0a32e0cSBarry Smith   comm = inmat->comm;
262b0a32e0cSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
263b0a32e0cSBarry Smith 
264b22afee1SSatish Balay   ierr = MatGetLocalSize(inmat,&m,0);CHKERRQ(ierr);
265b22afee1SSatish Balay   ierr = MatGetSize(inmat,&M,0);CHKERRQ(ierr);
266b0a32e0cSBarry Smith   ierr = VecCreateMPI(comm,m,M,&in);CHKERRQ(ierr);
267b0a32e0cSBarry Smith   ierr = VecDuplicate(in,&out);CHKERRQ(ierr);
268b0a32e0cSBarry Smith   ierr = VecGetOwnershipRange(in,&start,&end);CHKERRQ(ierr);
26938baddfdSBarry Smith   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&rows);CHKERRQ(ierr);
270b0a32e0cSBarry Smith   for (i=0; i<m; i++) {rows[i] = start + i;}
271b0a32e0cSBarry Smith 
272f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
273f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,m,M,M);CHKERRQ(ierr);
274b0a32e0cSBarry Smith   if (size == 1) {
275be5d1d56SKris Buschelman     ierr = MatSetType(*mat,MATSEQDENSE);CHKERRQ(ierr);
276be5d1d56SKris Buschelman     ierr = MatSeqDenseSetPreallocation(*mat,PETSC_NULL);CHKERRQ(ierr);
277b0a32e0cSBarry Smith   } else {
278be5d1d56SKris Buschelman     ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr);
279be5d1d56SKris Buschelman     ierr = MatMPIAIJSetPreallocation(*mat,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
280b0a32e0cSBarry Smith   }
281b0a32e0cSBarry Smith 
282b0a32e0cSBarry Smith   for (i=0; i<M; i++) {
283b0a32e0cSBarry Smith 
2842dcb1b2aSMatthew Knepley     ierr = VecSet(in,zero);CHKERRQ(ierr);
285b0a32e0cSBarry Smith     ierr = VecSetValues(in,1,&i,&one,INSERT_VALUES);CHKERRQ(ierr);
286b0a32e0cSBarry Smith     ierr = VecAssemblyBegin(in);CHKERRQ(ierr);
287b0a32e0cSBarry Smith     ierr = VecAssemblyEnd(in);CHKERRQ(ierr);
288b0a32e0cSBarry Smith 
289b0a32e0cSBarry Smith     ierr = MatMult(inmat,in,out);CHKERRQ(ierr);
290b0a32e0cSBarry Smith 
291b0a32e0cSBarry Smith     ierr = VecGetArray(out,&array);CHKERRQ(ierr);
292b0a32e0cSBarry Smith     ierr = MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
293b0a32e0cSBarry Smith     ierr = VecRestoreArray(out,&array);CHKERRQ(ierr);
294b0a32e0cSBarry Smith 
295b0a32e0cSBarry Smith   }
296b0a32e0cSBarry Smith   ierr = PetscFree(rows);CHKERRQ(ierr);
297b0a32e0cSBarry Smith   ierr = VecDestroy(out);CHKERRQ(ierr);
298b0a32e0cSBarry Smith   ierr = VecDestroy(in);CHKERRQ(ierr);
299b0a32e0cSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
300b0a32e0cSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
301b0a32e0cSBarry Smith   PetscFunctionReturn(0);
302b0a32e0cSBarry Smith }
303b0a32e0cSBarry Smith 
30424f910e3SHong Zhang /* Get the map xtoy which is used by MatAXPY() in the case of SUBSET_NONZERO_PATTERN */
30524f910e3SHong Zhang #undef __FUNCT__
30624f910e3SHong Zhang #define __FUNCT__ "MatAXPYGetxtoy_Private"
30738baddfdSBarry Smith PetscErrorCode MatAXPYGetxtoy_Private(PetscInt m,PetscInt *xi,PetscInt *xj,PetscInt *xgarray, PetscInt *yi,PetscInt *yj,PetscInt *ygarray, PetscInt **xtoy)
30824f910e3SHong Zhang {
3096849ba73SBarry Smith   PetscErrorCode ierr;
31038baddfdSBarry Smith   PetscInt       row,i,nz,xcol,ycol,jx,jy,*x2y;
31124f910e3SHong Zhang 
31224f910e3SHong Zhang   PetscFunctionBegin;
31338baddfdSBarry Smith   ierr = PetscMalloc(xi[m]*sizeof(PetscInt),&x2y);CHKERRQ(ierr);
31424f910e3SHong Zhang   i = 0;
31524f910e3SHong Zhang   for (row=0; row<m; row++){
31624f910e3SHong Zhang     nz = xi[1] - xi[0];
31724f910e3SHong Zhang     jy = 0;
31824f910e3SHong Zhang     for (jx=0; jx<nz; jx++,jy++){
31924f910e3SHong Zhang       if (xgarray && ygarray){
32024f910e3SHong Zhang         xcol = xgarray[xj[*xi + jx]];
32124f910e3SHong Zhang         ycol = ygarray[yj[*yi + jy]];
32224f910e3SHong Zhang       } else {
32324f910e3SHong Zhang         xcol = xj[*xi + jx];
32424f910e3SHong Zhang         ycol = yj[*yi + jy];  /* col index for y */
32524f910e3SHong Zhang       }
32624f910e3SHong Zhang       while ( ycol < xcol ) {
32724f910e3SHong Zhang         jy++;
32824f910e3SHong Zhang         if (ygarray){
32924f910e3SHong Zhang           ycol = ygarray[yj[*yi + jy]];
33024f910e3SHong Zhang         } else {
33124f910e3SHong Zhang           ycol = yj[*yi + jy];
33224f910e3SHong Zhang         }
33324f910e3SHong Zhang       }
33477431f27SBarry Smith       if (xcol != ycol) SETERRQ2(PETSC_ERR_ARG_WRONG,"X matrix entry (%D,%D) is not in Y matrix",row,ycol);
33524f910e3SHong Zhang       x2y[i++] = *yi + jy;
33624f910e3SHong Zhang     }
33724f910e3SHong Zhang     xi++; yi++;
33824f910e3SHong Zhang   }
33924f910e3SHong Zhang   *xtoy = x2y;
34024f910e3SHong Zhang   PetscFunctionReturn(0);
34124f910e3SHong Zhang }
342