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