xref: /petsc/src/mat/impls/aij/seq/fdaij.c (revision 6849ba73f22fecb8f92ef896a42e4e8bd4cd6965)
1 
2 #include "src/mat/impls/aij/seq/aij.h"
3 
4 EXTERN PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat,int,PetscTruth,int*,int*[],int*[],PetscTruth*);
5 EXTERN PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat,int,PetscTruth,int*,int*[],int*[],PetscTruth*);
6 
7 #undef __FUNCT__
8 #define __FUNCT__ "MatFDColoringCreate_SeqAIJ"
9 PetscErrorCode MatFDColoringCreate_SeqAIJ(Mat mat,ISColoring iscoloring,MatFDColoring c)
10 {
11   PetscErrorCode ierr;
12   int        i,*is,n,nrows,N = mat->N,j,k,m,*rows,*ci,*cj,ncols,col;
13   int        nis = iscoloring->n,*rowhit,*columnsforrow,l;
14   IS         *isa;
15   PetscTruth done,flg;
16 
17   PetscFunctionBegin;
18   if (!mat->assembled) {
19     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
20   }
21 
22   ierr = ISColoringGetIS(iscoloring,PETSC_IGNORE,&isa);CHKERRQ(ierr);
23   c->M       = mat->M;  /* set total rows, columns and local rows */
24   c->N       = mat->N;
25   c->m       = mat->M;
26   c->rstart  = 0;
27 
28   c->ncolors = nis;
29   ierr       = PetscMalloc(nis*sizeof(int),&c->ncolumns);CHKERRQ(ierr);
30   ierr       = PetscMalloc(nis*sizeof(int*),&c->columns);CHKERRQ(ierr);
31   ierr       = PetscMalloc(nis*sizeof(int),&c->nrows);CHKERRQ(ierr);
32   ierr       = PetscMalloc(nis*sizeof(int*),&c->rows);CHKERRQ(ierr);
33   ierr       = PetscMalloc(nis*sizeof(int*),&c->columnsforrow);CHKERRQ(ierr);
34 
35   /*
36       Calls the _SeqAIJ() version of these routines to make sure it does not
37      get the reduced (by inodes) version of I and J
38   */
39   ierr = MatGetColumnIJ_SeqAIJ(mat,0,PETSC_FALSE,&ncols,&ci,&cj,&done);CHKERRQ(ierr);
40 
41   /*
42      Temporary option to allow for debugging/testing
43   */
44   ierr = PetscOptionsHasName(PETSC_NULL,"-matfdcoloring_slow",&flg);CHKERRQ(ierr);
45 
46   ierr = PetscMalloc((N+1)*sizeof(int),&rowhit);CHKERRQ(ierr);
47   ierr = PetscMalloc((N+1)*sizeof(int),&columnsforrow);CHKERRQ(ierr);
48 
49   for (i=0; i<nis; i++) {
50     ierr = ISGetLocalSize(isa[i],&n);CHKERRQ(ierr);
51     ierr = ISGetIndices(isa[i],&is);CHKERRQ(ierr);
52     c->ncolumns[i] = n;
53     if (n) {
54       ierr = PetscMalloc(n*sizeof(int),&c->columns[i]);CHKERRQ(ierr);
55       ierr = PetscMemcpy(c->columns[i],is,n*sizeof(int));CHKERRQ(ierr);
56     } else {
57       c->columns[i]  = 0;
58     }
59 
60     if (!flg) { /* ------------------------------------------------------------------------------*/
61       /* fast, crude version requires O(N*N) work */
62       ierr = PetscMemzero(rowhit,N*sizeof(int));CHKERRQ(ierr);
63       /* loop over columns*/
64       for (j=0; j<n; j++) {
65         col  = is[j];
66         rows = cj + ci[col];
67         m    = ci[col+1] - ci[col];
68         /* loop over columns marking them in rowhit */
69         for (k=0; k<m; k++) {
70           rowhit[*rows++] = col + 1;
71         }
72       }
73       /* count the number of hits */
74       nrows = 0;
75       for (j=0; j<N; j++) {
76         if (rowhit[j]) nrows++;
77       }
78       c->nrows[i] = nrows;
79       ierr        = PetscMalloc((nrows+1)*sizeof(int),&c->rows[i]);CHKERRQ(ierr);
80       ierr        = PetscMalloc((nrows+1)*sizeof(int),&c->columnsforrow[i]);CHKERRQ(ierr);
81       nrows       = 0;
82       for (j=0; j<N; j++) {
83         if (rowhit[j]) {
84           c->rows[i][nrows]          = j;
85           c->columnsforrow[i][nrows] = rowhit[j] - 1;
86           nrows++;
87         }
88       }
89     } else {  /*-------------------------------------------------------------------------------*/
90       /* slow version, using rowhit as a linked list */
91       int currentcol,fm,mfm;
92       rowhit[N] = N;
93       nrows     = 0;
94       /* loop over columns */
95       for (j=0; j<n; j++) {
96         col   = is[j];
97         rows  = cj + ci[col];
98         m     = ci[col+1] - ci[col];
99         /* loop over columns marking them in rowhit */
100         fm    = N; /* fm points to first entry in linked list */
101         for (k=0; k<m; k++) {
102           currentcol = *rows++;
103 	  /* is it already in the list? */
104           do {
105             mfm  = fm;
106             fm   = rowhit[fm];
107           } while (fm < currentcol);
108           /* not in list so add it */
109           if (fm != currentcol) {
110             nrows++;
111             columnsforrow[currentcol] = col;
112             /* next three lines insert new entry into linked list */
113             rowhit[mfm]               = currentcol;
114             rowhit[currentcol]        = fm;
115             fm                        = currentcol;
116             /* fm points to present position in list since we know the columns are sorted */
117           } else {
118             SETERRQ(PETSC_ERR_PLIB,"Detected invalid coloring");
119           }
120 
121         }
122       }
123       c->nrows[i] = nrows;
124       ierr        = PetscMalloc((nrows+1)*sizeof(int),&c->rows[i]);CHKERRQ(ierr);
125       ierr        = PetscMalloc((nrows+1)*sizeof(int),&c->columnsforrow[i]);CHKERRQ(ierr);
126       /* now store the linked list of rows into c->rows[i] */
127       nrows       = 0;
128       fm          = rowhit[N];
129       do {
130         c->rows[i][nrows]            = fm;
131         c->columnsforrow[i][nrows++] = columnsforrow[fm];
132         fm                           = rowhit[fm];
133       } while (fm < N);
134     } /* ---------------------------------------------------------------------------------------*/
135     ierr = ISRestoreIndices(isa[i],&is);CHKERRQ(ierr);
136   }
137   ierr = MatRestoreColumnIJ_SeqAIJ(mat,0,PETSC_FALSE,&ncols,&ci,&cj,&done);CHKERRQ(ierr);
138 
139   ierr = PetscFree(rowhit);CHKERRQ(ierr);
140   ierr = PetscFree(columnsforrow);CHKERRQ(ierr);
141 
142   /* Optimize by adding the vscale, and scaleforrow[][] fields */
143   /*
144        see the version for MPIAIJ
145   */
146   ierr = VecCreateGhost(mat->comm,mat->m,PETSC_DETERMINE,0,PETSC_NULL,&c->vscale);CHKERRQ(ierr)
147   ierr = PetscMalloc(c->ncolors*sizeof(int*),&c->vscaleforrow);CHKERRQ(ierr);
148   for (k=0; k<c->ncolors; k++) {
149     ierr = PetscMalloc((c->nrows[k]+1)*sizeof(int),&c->vscaleforrow[k]);CHKERRQ(ierr);
150     for (l=0; l<c->nrows[k]; l++) {
151       col = c->columnsforrow[k][l];
152       c->vscaleforrow[k][l] = col;
153     }
154   }
155   ierr = ISColoringRestoreIS(iscoloring,&isa);CHKERRQ(ierr);
156   PetscFunctionReturn(0);
157 }
158 
159 /*
160      Makes a longer coloring[] array and calls the usual code with that
161 */
162 #undef __FUNCT__
163 #define __FUNCT__ "MatColoringPatch_SeqAIJ_Inode"
164 PetscErrorCode MatColoringPatch_SeqAIJ_Inode(Mat mat,int nin,int ncolors,const ISColoringValue coloring[],ISColoring *iscoloring)
165 {
166   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)mat->data;
167   PetscErrorCode ierr;
168   int             n = mat->n,m = a->inode.node_count,j,*ns = a->inode.size,row;
169   int             *colorused,i;
170   ISColoringValue *newcolor;
171 
172   PetscFunctionBegin;
173   ierr = PetscMalloc((n+1)*sizeof(int),&newcolor);CHKERRQ(ierr);
174   /* loop over inodes, marking a color for each column*/
175   row = 0;
176   for (i=0; i<m; i++){
177     for (j=0; j<ns[i]; j++) {
178       newcolor[row++] = coloring[i] + j*ncolors;
179     }
180   }
181 
182   /* eliminate unneeded colors */
183   ierr = PetscMalloc(5*ncolors*sizeof(int),&colorused);CHKERRQ(ierr);
184   ierr = PetscMemzero(colorused,5*ncolors*sizeof(int));CHKERRQ(ierr);
185   for (i=0; i<n; i++) {
186     colorused[newcolor[i]] = 1;
187   }
188 
189   for (i=1; i<5*ncolors; i++) {
190     colorused[i] += colorused[i-1];
191   }
192   ncolors = colorused[5*ncolors-1];
193   for (i=0; i<n; i++) {
194     newcolor[i] = colorused[newcolor[i]];
195   }
196   ierr = PetscFree(colorused);CHKERRQ(ierr);
197   ierr = ISColoringCreate(mat->comm,n,newcolor,iscoloring);CHKERRQ(ierr);
198   ierr = PetscFree((void*)coloring);CHKERRQ(ierr);
199   PetscFunctionReturn(0);
200 }
201 
202 
203 
204 
205 
206 
207