xref: /petsc/src/mat/impls/aij/seq/fdaij.c (revision 79c1e64d36b9636f4d05efb26e1dc611e5396174)
170c3da92SBarry Smith 
2c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>
3639f9d9dSBarry Smith 
4*79c1e64dSHong Zhang /*
5*79c1e64dSHong Zhang  Redundant - remove later!
6*79c1e64dSHong Zhang */
7*79c1e64dSHong Zhang #undef __FUNCT__
8*79c1e64dSHong Zhang #define __FUNCT__ "MatGetColumnIJ_SeqAIJ_Color_Redundant"
9*79c1e64dSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color_Redundant(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
10*79c1e64dSHong Zhang {
11*79c1e64dSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
12*79c1e64dSHong Zhang   PetscErrorCode ierr;
13*79c1e64dSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
14*79c1e64dSHong Zhang   PetscInt       nz = a->i[m],row,*jj,mr,col;
15*79c1e64dSHong Zhang   PetscInt       *cspidx;
16*79c1e64dSHong Zhang 
17*79c1e64dSHong Zhang   PetscFunctionBegin;
18*79c1e64dSHong Zhang   *nn = n;
19*79c1e64dSHong Zhang   if (!ia) PetscFunctionReturn(0);
20*79c1e64dSHong Zhang   if (symmetric) {
21*79c1e64dSHong Zhang     SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatGetColumnIJ_SeqAIJ_Color() not supported for the case symmetric");
22*79c1e64dSHong Zhang     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
23*79c1e64dSHong Zhang   } else {
24*79c1e64dSHong Zhang     ierr = PetscMalloc((n+1)*sizeof(PetscInt),&collengths);CHKERRQ(ierr);
25*79c1e64dSHong Zhang     ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr);
26*79c1e64dSHong Zhang     ierr = PetscMalloc((n+1)*sizeof(PetscInt),&cia);CHKERRQ(ierr);
27*79c1e64dSHong Zhang     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&cja);CHKERRQ(ierr);
28*79c1e64dSHong Zhang     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&cspidx);CHKERRQ(ierr);
29*79c1e64dSHong Zhang     jj   = a->j;
30*79c1e64dSHong Zhang     for (i=0; i<nz; i++) {
31*79c1e64dSHong Zhang       collengths[jj[i]]++;
32*79c1e64dSHong Zhang     }
33*79c1e64dSHong Zhang     cia[0] = oshift;
34*79c1e64dSHong Zhang     for (i=0; i<n; i++) {
35*79c1e64dSHong Zhang       cia[i+1] = cia[i] + collengths[i];
36*79c1e64dSHong Zhang     }
37*79c1e64dSHong Zhang     ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr);
38*79c1e64dSHong Zhang     jj   = a->j;
39*79c1e64dSHong Zhang     for (row=0; row<m; row++) {
40*79c1e64dSHong Zhang       mr = a->i[row+1] - a->i[row];
41*79c1e64dSHong Zhang       for (i=0; i<mr; i++) {
42*79c1e64dSHong Zhang         col = *jj++;
43*79c1e64dSHong Zhang 
44*79c1e64dSHong Zhang         cspidx[cia[col] + collengths[col] - oshift] = a->i[row] + i; /* index of a->j */
45*79c1e64dSHong Zhang         cja[cia[col] + collengths[col]++ - oshift]  = row + oshift;
46*79c1e64dSHong Zhang       }
47*79c1e64dSHong Zhang     }
48*79c1e64dSHong Zhang     ierr   = PetscFree(collengths);CHKERRQ(ierr);
49*79c1e64dSHong Zhang     *ia    = cia; *ja = cja;
50*79c1e64dSHong Zhang     *spidx = cspidx;
51*79c1e64dSHong Zhang   }
52*79c1e64dSHong Zhang   PetscFunctionReturn(0);
53*79c1e64dSHong Zhang }
54*79c1e64dSHong Zhang 
55*79c1e64dSHong Zhang #undef __FUNCT__
56*79c1e64dSHong Zhang #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ_Color_Redundant"
57*79c1e64dSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color_Redundant(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
58*79c1e64dSHong Zhang {
59*79c1e64dSHong Zhang   PetscErrorCode ierr;
60*79c1e64dSHong Zhang 
61*79c1e64dSHong Zhang   PetscFunctionBegin;
62*79c1e64dSHong Zhang   if (!ia) PetscFunctionReturn(0);
63*79c1e64dSHong Zhang 
64*79c1e64dSHong Zhang   ierr = PetscFree(*ia);CHKERRQ(ierr);
65*79c1e64dSHong Zhang   ierr = PetscFree(*ja);CHKERRQ(ierr);
66*79c1e64dSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
67*79c1e64dSHong Zhang   PetscFunctionReturn(0);
68*79c1e64dSHong Zhang }
69*79c1e64dSHong Zhang 
70*79c1e64dSHong Zhang /* -------------------------------------------*/
71*79c1e64dSHong Zhang 
72*79c1e64dSHong Zhang #undef __FUNCT__
73*79c1e64dSHong Zhang #define __FUNCT__ "MatFDColoringCreate_SeqAIJ_den2sp"
74*79c1e64dSHong Zhang /*
75*79c1e64dSHong Zhang     This routine optimizes MatFDColoringCreate_SeqAIJ() by using den2sp array
76*79c1e64dSHong Zhang */
77*79c1e64dSHong Zhang PetscErrorCode MatFDColoringCreate_SeqAIJ_den2sp(Mat mat,ISColoring iscoloring,MatFDColoring c)
78*79c1e64dSHong Zhang {
79*79c1e64dSHong Zhang   PetscErrorCode ierr;
80*79c1e64dSHong Zhang   PetscInt       i,n,nrows,N,j,k,m,ncols,col;
81*79c1e64dSHong Zhang   const PetscInt *is,*rows,*ci,*cj;
82*79c1e64dSHong Zhang   PetscInt       nis = iscoloring->n,*rowhit,*columnsforrow,l,bs = 1,*spidx,*spidxhit,*den2sp,*den2sp_i;
83*79c1e64dSHong Zhang   IS             *isa;
84*79c1e64dSHong Zhang   PetscBool      flg1,flg2;
85*79c1e64dSHong Zhang   Mat_SeqAIJ     *csp = (Mat_SeqAIJ*)mat->data;
86*79c1e64dSHong Zhang 
87*79c1e64dSHong Zhang   PetscFunctionBegin;
88*79c1e64dSHong Zhang   printf("MatFDColoringCreate_SeqAIJ_den2sp ...\n");
89*79c1e64dSHong Zhang   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
90*79c1e64dSHong Zhang 
91*79c1e64dSHong Zhang   ierr = ISColoringGetIS(iscoloring,PETSC_IGNORE,&isa);CHKERRQ(ierr);
92*79c1e64dSHong Zhang   /* this is ugly way to get blocksize but cannot call MatGetBlockSize() because AIJ can have bs > 1 */
93*79c1e64dSHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)mat,MATSEQBAIJ,&flg1);CHKERRQ(ierr);
94*79c1e64dSHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)mat,MATMPIBAIJ,&flg2);CHKERRQ(ierr);
95*79c1e64dSHong Zhang   if (flg1 || flg2) {
96*79c1e64dSHong Zhang     ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
97*79c1e64dSHong Zhang   }
98*79c1e64dSHong Zhang 
99*79c1e64dSHong Zhang   N         = mat->cmap->N/bs;
100*79c1e64dSHong Zhang   c->M      = mat->rmap->N/bs;   /* set total rows, columns and local rows */
101*79c1e64dSHong Zhang   c->N      = mat->cmap->N/bs;
102*79c1e64dSHong Zhang   c->m      = mat->rmap->N/bs;
103*79c1e64dSHong Zhang   c->rstart = 0;
104*79c1e64dSHong Zhang 
105*79c1e64dSHong Zhang   c->ncolors = nis;
106*79c1e64dSHong Zhang   ierr       = PetscMalloc(nis*sizeof(PetscInt),&c->ncolumns);CHKERRQ(ierr);
107*79c1e64dSHong Zhang   ierr       = PetscMalloc(nis*sizeof(PetscInt*),&c->columns);CHKERRQ(ierr);
108*79c1e64dSHong Zhang   ierr       = PetscMalloc(nis*sizeof(PetscInt),&c->nrows);CHKERRQ(ierr);
109*79c1e64dSHong Zhang   ierr       = PetscMalloc(nis*sizeof(PetscInt*),&c->rows);CHKERRQ(ierr);
110*79c1e64dSHong Zhang   ierr       = PetscMalloc(nis*sizeof(PetscInt*),&c->columnsforrow);CHKERRQ(ierr);
111*79c1e64dSHong Zhang   ierr       = PetscMalloc((csp->nz+1)*sizeof(PetscInt),&den2sp);CHKERRQ(ierr);
112*79c1e64dSHong Zhang   den2sp_i   = den2sp;
113*79c1e64dSHong Zhang 
114*79c1e64dSHong Zhang   ierr = MatGetColumnIJ_SeqAIJ_Color_Redundant(mat,0,PETSC_FALSE,PETSC_FALSE,&ncols,&ci,&cj,&spidx,NULL);CHKERRQ(ierr);
115*79c1e64dSHong Zhang 
116*79c1e64dSHong Zhang   ierr = PetscMalloc((c->m+1)*sizeof(PetscInt),&rowhit);CHKERRQ(ierr);
117*79c1e64dSHong Zhang   ierr = PetscMemzero(rowhit,c->m*sizeof(PetscInt));CHKERRQ(ierr);
118*79c1e64dSHong Zhang   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&columnsforrow);CHKERRQ(ierr); // N=mat->cmap->N/bs or c->M ?
119*79c1e64dSHong Zhang   ierr = PetscMalloc((c->m+1)*sizeof(PetscInt),&spidxhit);CHKERRQ(ierr);
120*79c1e64dSHong Zhang 
121*79c1e64dSHong Zhang   for (i=0; i<nis; i++) { /* loop over colors */
122*79c1e64dSHong Zhang     ierr = ISGetLocalSize(isa[i],&n);CHKERRQ(ierr);
123*79c1e64dSHong Zhang     ierr = ISGetIndices(isa[i],&is);CHKERRQ(ierr);
124*79c1e64dSHong Zhang 
125*79c1e64dSHong Zhang     c->ncolumns[i] = n;
126*79c1e64dSHong Zhang     if (n) {
127*79c1e64dSHong Zhang       ierr = PetscMalloc(n*sizeof(PetscInt),&c->columns[i]);CHKERRQ(ierr);
128*79c1e64dSHong Zhang       ierr = PetscMemcpy(c->columns[i],is,n*sizeof(PetscInt));CHKERRQ(ierr);
129*79c1e64dSHong Zhang     } else {
130*79c1e64dSHong Zhang       c->columns[i] = 0;
131*79c1e64dSHong Zhang     }
132*79c1e64dSHong Zhang 
133*79c1e64dSHong Zhang     /* fast, crude version requires O(N*N) work */
134*79c1e64dSHong Zhang     for (j=0; j<n; j++) {  /* loop over columns */
135*79c1e64dSHong Zhang       col  = is[j];
136*79c1e64dSHong Zhang       rows = cj + ci[col];
137*79c1e64dSHong Zhang       m    = ci[col+1] - ci[col];
138*79c1e64dSHong Zhang       for (k=0; k<m; k++) {  /* loop over columns marking them in rowhit */
139*79c1e64dSHong Zhang         rowhit[*rows]   = col + 1;
140*79c1e64dSHong Zhang         spidxhit[*rows] = spidx[ci[col] + k];
141*79c1e64dSHong Zhang         rows++;
142*79c1e64dSHong Zhang       }
143*79c1e64dSHong Zhang     }
144*79c1e64dSHong Zhang     /* get num of rows by counting the number of hits */
145*79c1e64dSHong Zhang     nrows = 0;
146*79c1e64dSHong Zhang     for (j=0; j<N; j++) {
147*79c1e64dSHong Zhang       if (rowhit[j]) nrows++;
148*79c1e64dSHong Zhang     }
149*79c1e64dSHong Zhang     c->nrows[i] = nrows;
150*79c1e64dSHong Zhang 
151*79c1e64dSHong Zhang     ierr = PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);CHKERRQ(ierr);
152*79c1e64dSHong Zhang     ierr = PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);CHKERRQ(ierr);
153*79c1e64dSHong Zhang     nrows = 0;
154*79c1e64dSHong Zhang     for (j=0; j<N; j++) { /* loop over rows */
155*79c1e64dSHong Zhang       if (rowhit[j]) {
156*79c1e64dSHong Zhang         c->rows[i][nrows]          = j;             /* row index */
157*79c1e64dSHong Zhang         c->columnsforrow[i][nrows] = rowhit[j] - 1; /* column index */
158*79c1e64dSHong Zhang         den2sp_i[nrows++]          = spidxhit[j];
159*79c1e64dSHong Zhang         rowhit[j] = 0.0; /* zero rowhit for reuse */
160*79c1e64dSHong Zhang       }
161*79c1e64dSHong Zhang     }
162*79c1e64dSHong Zhang     den2sp_i += nrows;
163*79c1e64dSHong Zhang     ierr = ISRestoreIndices(isa[i],&is);CHKERRQ(ierr);
164*79c1e64dSHong Zhang   }
165*79c1e64dSHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ_Color_Redundant(mat,0,PETSC_FALSE,PETSC_FALSE,&ncols,&ci,&cj,&spidx,NULL);CHKERRQ(ierr);
166*79c1e64dSHong Zhang 
167*79c1e64dSHong Zhang   ierr = PetscFree(rowhit);CHKERRQ(ierr);
168*79c1e64dSHong Zhang   ierr = PetscFree(columnsforrow);CHKERRQ(ierr);
169*79c1e64dSHong Zhang   ierr = PetscFree(spidxhit);CHKERRQ(ierr);
170*79c1e64dSHong Zhang 
171*79c1e64dSHong Zhang   /* Optimize by adding the vscale, and scaleforrow[][] fields -- needed for seqaij??? */
172*79c1e64dSHong Zhang   /*
173*79c1e64dSHong Zhang        see the version for MPIAIJ
174*79c1e64dSHong Zhang   */
175*79c1e64dSHong Zhang   ierr = VecCreateGhost(PetscObjectComm((PetscObject)mat),mat->rmap->n,PETSC_DETERMINE,0,NULL,&c->vscale);CHKERRQ(ierr);
176*79c1e64dSHong Zhang   ierr = PetscMalloc(c->ncolors*sizeof(PetscInt*),&c->vscaleforrow);CHKERRQ(ierr);
177*79c1e64dSHong Zhang   for (k=0; k<c->ncolors; k++) {
178*79c1e64dSHong Zhang     ierr = PetscMalloc((c->nrows[k]+1)*sizeof(PetscInt),&c->vscaleforrow[k]);CHKERRQ(ierr);
179*79c1e64dSHong Zhang     for (l=0; l<c->nrows[k]; l++) {
180*79c1e64dSHong Zhang       col = c->columnsforrow[k][l];
181*79c1e64dSHong Zhang 
182*79c1e64dSHong Zhang       c->vscaleforrow[k][l] = col;
183*79c1e64dSHong Zhang     }
184*79c1e64dSHong Zhang   }
185*79c1e64dSHong Zhang   ierr = ISColoringRestoreIS(iscoloring,&isa);CHKERRQ(ierr);
186*79c1e64dSHong Zhang   c->den2sp                 = den2sp;
187*79c1e64dSHong Zhang   mat->ops->fdcoloringapply = MatFDColoringApply_SeqAIJ;
188*79c1e64dSHong Zhang   PetscFunctionReturn(0);
189*79c1e64dSHong Zhang }
190*79c1e64dSHong Zhang 
191*79c1e64dSHong Zhang /* --------------------------------------------------------------- */
192*79c1e64dSHong Zhang 
1934a2ae208SSatish Balay #undef __FUNCT__
1944a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringCreate_SeqAIJ"
1953acb8795SBarry Smith /*
1963acb8795SBarry Smith     This routine is shared by AIJ and BAIJ matrices, since it operators only on the nonzero structure of the elements or blocks.
1973acb8795SBarry Smith     This is why it has the ugly code with the MatGetBlockSize()
1983acb8795SBarry Smith */
199dfbe8321SBarry Smith PetscErrorCode MatFDColoringCreate_SeqAIJ(Mat mat,ISColoring iscoloring,MatFDColoring c)
200639f9d9dSBarry Smith {
2016849ba73SBarry Smith   PetscErrorCode ierr;
2021a83f524SJed Brown   PetscInt       i,n,nrows,N,j,k,m,ncols,col;
2031a83f524SJed Brown   const PetscInt *is,*rows,*ci,*cj;
2043acb8795SBarry Smith   PetscInt       nis = iscoloring->n,*rowhit,*columnsforrow,l,bs = 1;
205b9617806SBarry Smith   IS             *isa;
206ace3abfcSBarry Smith   PetscBool      done,flg = PETSC_FALSE;
207ace3abfcSBarry Smith   PetscBool      flg1,flg2;
208*79c1e64dSHong Zhang   PetscBool      new_impl=PETSC_FALSE;
209639f9d9dSBarry Smith 
2103a40ed3dSBarry Smith   PetscFunctionBegin;
211*79c1e64dSHong Zhang   printf("MatFDColoringCreate_SeqAIJ ...\n");
212*79c1e64dSHong Zhang   ierr = PetscOptionsName("-new","using new impls","",&new_impl);CHKERRQ(ierr);
213*79c1e64dSHong Zhang   if (new_impl){
214*79c1e64dSHong Zhang     ierr =  MatFDColoringCreate_SeqAIJ_den2sp(mat,iscoloring,c);CHKERRQ(ierr);
215*79c1e64dSHong Zhang     PetscFunctionReturn(0);
216*79c1e64dSHong Zhang   }
217e7e72b3dSBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
218522c5e43SBarry Smith 
219b9617806SBarry Smith   ierr = ISColoringGetIS(iscoloring,PETSC_IGNORE,&isa);CHKERRQ(ierr);
2203acb8795SBarry Smith   /* this is ugly way to get blocksize but cannot call MatGetBlockSize() because AIJ can have bs > 1 */
221251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)mat,MATSEQBAIJ,&flg1);CHKERRQ(ierr);
222251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)mat,MATMPIBAIJ,&flg2);CHKERRQ(ierr);
2233acb8795SBarry Smith   if (flg1 || flg2) {
2243acb8795SBarry Smith     ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
2253acb8795SBarry Smith   }
2263acb8795SBarry Smith 
2273acb8795SBarry Smith   N         = mat->cmap->N/bs;
2283acb8795SBarry Smith   c->M      = mat->rmap->N/bs;   /* set total rows, columns and local rows */
2293acb8795SBarry Smith   c->N      = mat->cmap->N/bs;
2303acb8795SBarry Smith   c->m      = mat->rmap->N/bs;
231005c665bSBarry Smith   c->rstart = 0;
232005c665bSBarry Smith 
233639f9d9dSBarry Smith   c->ncolors = nis;
23438baddfdSBarry Smith   ierr       = PetscMalloc(nis*sizeof(PetscInt),&c->ncolumns);CHKERRQ(ierr);
23538baddfdSBarry Smith   ierr       = PetscMalloc(nis*sizeof(PetscInt*),&c->columns);CHKERRQ(ierr);
23638baddfdSBarry Smith   ierr       = PetscMalloc(nis*sizeof(PetscInt),&c->nrows);CHKERRQ(ierr);
23738baddfdSBarry Smith   ierr       = PetscMalloc(nis*sizeof(PetscInt*),&c->rows);CHKERRQ(ierr);
23838baddfdSBarry Smith   ierr       = PetscMalloc(nis*sizeof(PetscInt*),&c->columnsforrow);CHKERRQ(ierr);
23943a90d84SBarry Smith 
2403acb8795SBarry Smith   ierr = MatGetColumnIJ(mat,0,PETSC_FALSE,PETSC_FALSE,&ncols,&ci,&cj,&done);CHKERRQ(ierr);
241ce94432eSBarry Smith   if (!done) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"MatGetColumnIJ() not supported for matrix type %s",((PetscObject)mat)->type_name);
24270c3da92SBarry Smith 
24370c3da92SBarry Smith   /*
244639f9d9dSBarry Smith      Temporary option to allow for debugging/testing
24570c3da92SBarry Smith   */
2460298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-matfdcoloring_slow",&flg,NULL);CHKERRQ(ierr);
24770c3da92SBarry Smith 
24838baddfdSBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&rowhit);CHKERRQ(ierr);
24938baddfdSBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&columnsforrow);CHKERRQ(ierr);
25070c3da92SBarry Smith 
251639f9d9dSBarry Smith   for (i=0; i<nis; i++) {
252b9b97703SBarry Smith     ierr = ISGetLocalSize(isa[i],&n);CHKERRQ(ierr);
253639f9d9dSBarry Smith     ierr = ISGetIndices(isa[i],&is);CHKERRQ(ierr);
2542205254eSKarl Rupp 
255639f9d9dSBarry Smith     c->ncolumns[i] = n;
256639f9d9dSBarry Smith     if (n) {
25738baddfdSBarry Smith       ierr = PetscMalloc(n*sizeof(PetscInt),&c->columns[i]);CHKERRQ(ierr);
25838baddfdSBarry Smith       ierr = PetscMemcpy(c->columns[i],is,n*sizeof(PetscInt));CHKERRQ(ierr);
25970c3da92SBarry Smith     } else {
260639f9d9dSBarry Smith       c->columns[i] = 0;
26170c3da92SBarry Smith     }
26270c3da92SBarry Smith 
2633a7fca6bSBarry Smith     if (!flg) { /* ------------------------------------------------------------------------------*/
2643a7fca6bSBarry Smith       /* fast, crude version requires O(N*N) work */
26538baddfdSBarry Smith       ierr = PetscMemzero(rowhit,N*sizeof(PetscInt));CHKERRQ(ierr);
266639f9d9dSBarry Smith       /* loop over columns*/
267639f9d9dSBarry Smith       for (j=0; j<n; j++) {
268639f9d9dSBarry Smith         col  = is[j];
269639f9d9dSBarry Smith         rows = cj + ci[col];
270639f9d9dSBarry Smith         m    = ci[col+1] - ci[col];
271639f9d9dSBarry Smith         /* loop over columns marking them in rowhit */
272639f9d9dSBarry Smith         for (k=0; k<m; k++) {
273639f9d9dSBarry Smith           rowhit[*rows++] = col + 1;
27470c3da92SBarry Smith         }
27570c3da92SBarry Smith       }
276639f9d9dSBarry Smith       /* count the number of hits */
277639f9d9dSBarry Smith       nrows = 0;
27870c3da92SBarry Smith       for (j=0; j<N; j++) {
279639f9d9dSBarry Smith         if (rowhit[j]) nrows++;
280639f9d9dSBarry Smith       }
281639f9d9dSBarry Smith       c->nrows[i] = nrows;
28238baddfdSBarry Smith       ierr        = PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);CHKERRQ(ierr);
28338baddfdSBarry Smith       ierr        = PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);CHKERRQ(ierr);
284639f9d9dSBarry Smith       nrows       = 0;
285639f9d9dSBarry Smith       for (j=0; j<N; j++) {
286639f9d9dSBarry Smith         if (rowhit[j]) {
287639f9d9dSBarry Smith           c->rows[i][nrows]          = j;
288639f9d9dSBarry Smith           c->columnsforrow[i][nrows] = rowhit[j] - 1;
289639f9d9dSBarry Smith           nrows++;
29070c3da92SBarry Smith         }
29170c3da92SBarry Smith       }
292639f9d9dSBarry Smith     } else {  /*-------------------------------------------------------------------------------*/
2933a7fca6bSBarry Smith       /* slow version, using rowhit as a linked list */
29438baddfdSBarry Smith       PetscInt currentcol,fm,mfm;
295639f9d9dSBarry Smith       rowhit[N] = N;
296639f9d9dSBarry Smith       nrows     = 0;
297639f9d9dSBarry Smith       /* loop over columns */
298639f9d9dSBarry Smith       for (j=0; j<n; j++) {
299639f9d9dSBarry Smith         col  = is[j];
300639f9d9dSBarry Smith         rows = cj + ci[col];
301639f9d9dSBarry Smith         m    = ci[col+1] - ci[col];
302639f9d9dSBarry Smith         /* loop over columns marking them in rowhit */
303639f9d9dSBarry Smith         fm = N;    /* fm points to first entry in linked list */
304639f9d9dSBarry Smith         for (k=0; k<m; k++) {
305639f9d9dSBarry Smith           currentcol = *rows++;
306639f9d9dSBarry Smith           /* is it already in the list? */
307639f9d9dSBarry Smith           do {
308639f9d9dSBarry Smith             mfm = fm;
309639f9d9dSBarry Smith             fm  = rowhit[fm];
310639f9d9dSBarry Smith           } while (fm < currentcol);
311639f9d9dSBarry Smith           /* not in list so add it */
312639f9d9dSBarry Smith           if (fm != currentcol) {
313639f9d9dSBarry Smith             nrows++;
314639f9d9dSBarry Smith             columnsforrow[currentcol] = col;
315639f9d9dSBarry Smith             /* next three lines insert new entry into linked list */
316639f9d9dSBarry Smith             rowhit[mfm]        = currentcol;
317639f9d9dSBarry Smith             rowhit[currentcol] = fm;
318639f9d9dSBarry Smith             fm                 = currentcol;
319639f9d9dSBarry Smith             /* fm points to present position in list since we know the columns are sorted */
32071cd77b2SBarry Smith           } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Detected invalid coloring");
321639f9d9dSBarry Smith         }
322639f9d9dSBarry Smith       }
323639f9d9dSBarry Smith       c->nrows[i] = nrows;
32438baddfdSBarry Smith       ierr        = PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);CHKERRQ(ierr);
32538baddfdSBarry Smith       ierr        = PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);CHKERRQ(ierr);
326639f9d9dSBarry Smith       /* now store the linked list of rows into c->rows[i] */
327639f9d9dSBarry Smith       nrows = 0;
328639f9d9dSBarry Smith       fm    = rowhit[N];
329639f9d9dSBarry Smith       do {
330639f9d9dSBarry Smith         c->rows[i][nrows]            = fm;
331639f9d9dSBarry Smith         c->columnsforrow[i][nrows++] = columnsforrow[fm];
332639f9d9dSBarry Smith         fm                           = rowhit[fm];
333639f9d9dSBarry Smith       } while (fm < N);
334639f9d9dSBarry Smith     } /* ---------------------------------------------------------------------------------------*/
335639f9d9dSBarry Smith     ierr = ISRestoreIndices(isa[i],&is);CHKERRQ(ierr);
336639f9d9dSBarry Smith   }
3373acb8795SBarry Smith   ierr = MatRestoreColumnIJ(mat,0,PETSC_FALSE,PETSC_FALSE,&ncols,&ci,&cj,&done);CHKERRQ(ierr);
338639f9d9dSBarry Smith 
339606d414cSSatish Balay   ierr = PetscFree(rowhit);CHKERRQ(ierr);
340606d414cSSatish Balay   ierr = PetscFree(columnsforrow);CHKERRQ(ierr);
341639f9d9dSBarry Smith 
34230b34957SBarry Smith   /* Optimize by adding the vscale, and scaleforrow[][] fields */
34330b34957SBarry Smith   /*
34430b34957SBarry Smith        see the version for MPIAIJ
34530b34957SBarry Smith   */
346ce94432eSBarry Smith   ierr = VecCreateGhost(PetscObjectComm((PetscObject)mat),mat->rmap->n,PETSC_DETERMINE,0,NULL,&c->vscale);CHKERRQ(ierr);
34738baddfdSBarry Smith   ierr = PetscMalloc(c->ncolors*sizeof(PetscInt*),&c->vscaleforrow);CHKERRQ(ierr);
34830b34957SBarry Smith   for (k=0; k<c->ncolors; k++) {
34938baddfdSBarry Smith     ierr = PetscMalloc((c->nrows[k]+1)*sizeof(PetscInt),&c->vscaleforrow[k]);CHKERRQ(ierr);
35030b34957SBarry Smith     for (l=0; l<c->nrows[k]; l++) {
35130b34957SBarry Smith       col = c->columnsforrow[k][l];
3522205254eSKarl Rupp 
35330b34957SBarry Smith       c->vscaleforrow[k][l] = col;
35430b34957SBarry Smith     }
35530b34957SBarry Smith   }
356b9617806SBarry Smith   ierr = ISColoringRestoreIS(iscoloring,&isa);CHKERRQ(ierr);
3573a40ed3dSBarry Smith   PetscFunctionReturn(0);
35870c3da92SBarry Smith }
359*79c1e64dSHong Zhang 
360