Actual source code: fdaij.c
1: #define PETSCMAT_DLL
3: #include ../src/mat/impls/aij/seq/aij.h
7: /*
8: This routine is shared by AIJ and BAIJ matrices, since it operators only on the nonzero structure of the elements or blocks.
9: This is why it has the ugly code with the MatGetBlockSize()
10: */
11: PetscErrorCode MatFDColoringCreate_SeqAIJ(Mat mat,ISColoring iscoloring,MatFDColoring c)
12: {
14: PetscInt i,n,nrows,N,j,k,m,*rows,*ci,*cj,ncols,col;
15: const PetscInt *is;
16: PetscInt nis = iscoloring->n,*rowhit,*columnsforrow,l,bs = 1;
17: IS *isa;
18: PetscTruth done,flg = PETSC_FALSE;
19: PetscTruth flg1,flg2;
22: if (!mat->assembled) {
23: SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
24: }
26: ISColoringGetIS(iscoloring,PETSC_IGNORE,&isa);
27: /* this is ugly way to get blocksize but cannot call MatGetBlockSize() because AIJ can have bs > 1 */
28: PetscTypeCompare((PetscObject)mat,MATSEQBAIJ,&flg1);
29: PetscTypeCompare((PetscObject)mat,MATMPIBAIJ,&flg2);
30: if (flg1 || flg2) {
31: MatGetBlockSize(mat,&bs);
32: }
34: N = mat->cmap->N/bs;
35: c->M = mat->rmap->N/bs; /* set total rows, columns and local rows */
36: c->N = mat->cmap->N/bs;
37: c->m = mat->rmap->N/bs;
38: c->rstart = 0;
40: c->ncolors = nis;
41: PetscMalloc(nis*sizeof(PetscInt),&c->ncolumns);
42: PetscMalloc(nis*sizeof(PetscInt*),&c->columns);
43: PetscMalloc(nis*sizeof(PetscInt),&c->nrows);
44: PetscMalloc(nis*sizeof(PetscInt*),&c->rows);
45: PetscMalloc(nis*sizeof(PetscInt*),&c->columnsforrow);
47: MatGetColumnIJ(mat,0,PETSC_FALSE,PETSC_FALSE,&ncols,&ci,&cj,&done);
48: if (!done) SETERRQ1(PETSC_ERR_SUP,"MatGetColumnIJ() not supported for matrix type %s",((PetscObject)mat)->type_name);
50: /*
51: Temporary option to allow for debugging/testing
52: */
53: PetscOptionsGetTruth(PETSC_NULL,"-matfdcoloring_slow",&flg,PETSC_NULL);
55: PetscMalloc((N+1)*sizeof(PetscInt),&rowhit);
56: PetscMalloc((N+1)*sizeof(PetscInt),&columnsforrow);
58: for (i=0; i<nis; i++) {
59: ISGetLocalSize(isa[i],&n);
60: ISGetIndices(isa[i],&is);
61: c->ncolumns[i] = n;
62: if (n) {
63: PetscMalloc(n*sizeof(PetscInt),&c->columns[i]);
64: PetscMemcpy(c->columns[i],is,n*sizeof(PetscInt));
65: } else {
66: c->columns[i] = 0;
67: }
69: if (!flg) { /* ------------------------------------------------------------------------------*/
70: /* fast, crude version requires O(N*N) work */
71: PetscMemzero(rowhit,N*sizeof(PetscInt));
72: /* loop over columns*/
73: for (j=0; j<n; j++) {
74: col = is[j];
75: rows = cj + ci[col];
76: m = ci[col+1] - ci[col];
77: /* loop over columns marking them in rowhit */
78: for (k=0; k<m; k++) {
79: rowhit[*rows++] = col + 1;
80: }
81: }
82: /* count the number of hits */
83: nrows = 0;
84: for (j=0; j<N; j++) {
85: if (rowhit[j]) nrows++;
86: }
87: c->nrows[i] = nrows;
88: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);
89: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);
90: nrows = 0;
91: for (j=0; j<N; j++) {
92: if (rowhit[j]) {
93: c->rows[i][nrows] = j;
94: c->columnsforrow[i][nrows] = rowhit[j] - 1;
95: nrows++;
96: }
97: }
98: } else { /*-------------------------------------------------------------------------------*/
99: /* slow version, using rowhit as a linked list */
100: PetscInt currentcol,fm,mfm;
101: rowhit[N] = N;
102: nrows = 0;
103: /* loop over columns */
104: for (j=0; j<n; j++) {
105: col = is[j];
106: rows = cj + ci[col];
107: m = ci[col+1] - ci[col];
108: /* loop over columns marking them in rowhit */
109: fm = N; /* fm points to first entry in linked list */
110: for (k=0; k<m; k++) {
111: currentcol = *rows++;
112: /* is it already in the list? */
113: do {
114: mfm = fm;
115: fm = rowhit[fm];
116: } while (fm < currentcol);
117: /* not in list so add it */
118: if (fm != currentcol) {
119: nrows++;
120: columnsforrow[currentcol] = col;
121: /* next three lines insert new entry into linked list */
122: rowhit[mfm] = currentcol;
123: rowhit[currentcol] = fm;
124: fm = currentcol;
125: /* fm points to present position in list since we know the columns are sorted */
126: } else {
127: SETERRQ(PETSC_ERR_PLIB,"Detected invalid coloring");
128: }
130: }
131: }
132: c->nrows[i] = nrows;
133: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->rows[i]);
134: PetscMalloc((nrows+1)*sizeof(PetscInt),&c->columnsforrow[i]);
135: /* now store the linked list of rows into c->rows[i] */
136: nrows = 0;
137: fm = rowhit[N];
138: do {
139: c->rows[i][nrows] = fm;
140: c->columnsforrow[i][nrows++] = columnsforrow[fm];
141: fm = rowhit[fm];
142: } while (fm < N);
143: } /* ---------------------------------------------------------------------------------------*/
144: ISRestoreIndices(isa[i],&is);
145: }
146: MatRestoreColumnIJ(mat,0,PETSC_FALSE,PETSC_FALSE,&ncols,&ci,&cj,&done);
148: PetscFree(rowhit);
149: PetscFree(columnsforrow);
151: /* Optimize by adding the vscale, and scaleforrow[][] fields */
152: /*
153: see the version for MPIAIJ
154: */
155: VecCreateGhost(((PetscObject)mat)->comm,mat->rmap->n,PETSC_DETERMINE,0,PETSC_NULL,&c->vscale);CHKERRQ(ierr)
156: PetscMalloc(c->ncolors*sizeof(PetscInt*),&c->vscaleforrow);
157: for (k=0; k<c->ncolors; k++) {
158: PetscMalloc((c->nrows[k]+1)*sizeof(PetscInt),&c->vscaleforrow[k]);
159: for (l=0; l<c->nrows[k]; l++) {
160: col = c->columnsforrow[k][l];
161: c->vscaleforrow[k][l] = col;
162: }
163: }
164: ISColoringRestoreIS(iscoloring,&isa);
165: return(0);
166: }