xref: /petsc/src/mat/impls/aij/mpi/fdmpiaij.c (revision 00a98328c1f4fb9da36b452d9383e7a2e935b046)
1 
2 
3 #ifndef lint
4 static char vcid[] = "$Id: fdmpiaij.c,v 1.2 1996/10/28 14:59:58 bsmith Exp bsmith $";
5 #endif
6 
7 #include "src/mat/impls/aij/mpi/mpiaij.h"
8 #include "src/vec/vecimpl.h"
9 #include "petsc.h"
10 
11 extern int CreateColmap_MPIAIJ_Private(Mat);
12 extern int MatGetColumnIJ_SeqAIJ(Mat,int,PetscTruth,int*,int**,int**,PetscTruth*);
13 extern int MatRestoreColumnIJ_SeqAIJ(Mat,int,PetscTruth,int*,int**,int**,PetscTruth*);
14 
15 int MatFDColoringCreate_MPIAIJ(Mat mat,ISColoring iscoloring,MatFDColoring c)
16 {
17   Mat_MPIAIJ *aij = (Mat_MPIAIJ *) mat->data;
18   int        i,*is,n,nrows,j,k,m,*rows = 0,ierr,*A_ci,*A_cj,ncols,col,flg;
19   int        nis = iscoloring->n,*ncolsonproc,size,nctot,*cols,*disp,*B_ci,*B_cj;
20   int        *rowhit, M = mat->m,cstart = aij->cstart, cend = aij->cend,colb;
21   int        *columnsforrow;
22   IS         *isa = iscoloring->is;
23   PetscTruth done;
24 
25   c->ncolors       = nis;
26   c->ncolumns      = (int *) PetscMalloc( nis*sizeof(int) );   CHKPTRQ(c->ncolumns);
27   c->columns       = (int **) PetscMalloc( nis*sizeof(int *)); CHKPTRQ(c->columns);
28   c->nrows         = (int *) PetscMalloc( nis*sizeof(int) );   CHKPTRQ(c->nrows);
29   c->rows          = (int **) PetscMalloc( nis*sizeof(int *)); CHKPTRQ(c->rows);
30   c->columnsforrow = (int **) PetscMalloc( nis*sizeof(int *)); CHKPTRQ(c->columnsforrow);
31 
32   /* Allow access to data structures of local part of matrix */
33   if (!aij->colmap) {
34     ierr = CreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr);
35   }
36   /*
37       Calls the _SeqAIJ() version of these routines to make sure it does not
38      get the reduced (by inodes) version of I and J
39   */
40   ierr = MatGetColumnIJ_SeqAIJ(aij->A,0,PETSC_FALSE,&ncols,&A_ci,&A_cj,&done); CHKERRQ(ierr);
41   ierr = MatGetColumnIJ_SeqAIJ(aij->B,0,PETSC_FALSE,&ncols,&B_ci,&B_cj,&done); CHKERRQ(ierr);
42 
43   MPI_Comm_size(mat->comm,&size);
44   ncolsonproc = (int *) PetscMalloc( 2*size*sizeof(int *) ); CHKPTRQ(ncolsonproc);
45   disp        = ncolsonproc + size;
46 
47   rowhit        = (int *) PetscMalloc( (M+1)*sizeof(int) ); CHKPTRQ(rowhit);
48   columnsforrow = (int *) PetscMalloc( (M+1)*sizeof(int) );CHKPTRQ(columnsforrow);
49 
50   /*
51      Temporary option to allow for debugging/testing
52   */
53   ierr = OptionsHasName(0,"-matfdcoloring_slow",&flg);
54 
55   for ( i=0; i<nis; i++ ) {
56     ierr = ISGetSize(isa[i],&n); CHKERRQ(ierr);
57     ierr = ISGetIndices(isa[i],&is); CHKERRQ(ierr);
58     c->ncolumns[i] = n;
59     c->ncolumns[i] = n;
60     if (n) {
61       c->columns[i]  = (int *) PetscMalloc( n*sizeof(int) ); CHKPTRQ(c->columns[i]);
62       PetscMemcpy(c->columns[i],is,n*sizeof(int));
63     } else {
64       c->columns[i]  = 0;
65     }
66 
67     /* Determine the total (parallel) number of columns of this color */
68     MPI_Allgather(&n,1,MPI_INT,ncolsonproc,1,MPI_INT,mat->comm);
69     nctot = 0; for ( j=0; j<size; j++ ) {nctot += ncolsonproc[j];}
70     if (!nctot) SETERRQ(1,"MatFDColoringCreate_MPIAIJ:Invalid coloring");
71 
72     disp[0] = 0;
73     for ( j=1; j<size; j++ ) {
74       disp[j] = disp[j-1] + ncolsonproc[j-1];
75     }
76 
77     /* Get complete list of columns for color on each processor */
78     cols = (int *) PetscMalloc( nctot*sizeof(int) ); CHKPTRQ(cols);
79     MPI_Allgatherv(is,n,MPI_INT,cols,ncolsonproc,disp,MPI_INT,mat->comm);
80 
81 /*
82 for ( j=0; j<nctot; j++ ) {
83   printf("color %d %d col %d\n",i,j,cols[j]);
84 }
85 */
86 
87     /*
88        Mark all rows affect by these columns
89     */
90     if (flg) {/*-----------------------------------------------------------------------------*/
91       /* crude, slow version */
92       PetscMemzero(rowhit,M*sizeof(int));
93       /* loop over columns*/
94       for ( j=0; j<nctot; j++ ) {
95         col  = cols[j];
96         if (col >= cstart && col < cend) {
97           /* column is in diagonal block of matrix */
98           rows = A_cj + A_ci[col-cstart];
99           m    = A_ci[col-cstart+1] - A_ci[col-cstart];
100         } else {
101           colb = aij->colmap[col] - 1;
102           if (colb == -1) {
103             m = 0;
104           } else {
105             rows = B_cj + B_ci[colb];
106             m    = B_ci[colb+1] - B_ci[colb];
107           }
108         }
109         /* loop over columns marking them in rowhit */
110         for ( k=0; k<m; k++ ) {
111           rowhit[*rows++] = col + 1;
112         }
113       }
114 
115 /*
116 printf("for col %d found rows \n",i);
117 for ( j=0; j<M; j++ ) printf("rhow hit %d %d\n",j,rowhit[j]);
118 */
119 
120       /* count the number of hits */
121       nrows = 0;
122       for ( j=0; j<M; j++ ) {
123         if (rowhit[j]) nrows++;
124       }
125       c->nrows[i]         = nrows;
126       c->rows[i]          = (int *) PetscMalloc((nrows+1)*sizeof(int)); CHKPTRQ(c->rows[i]);
127       c->columnsforrow[i] = (int *) PetscMalloc((nrows+1)*sizeof(int)); CHKPTRQ(c->columnsforrow[i]);
128       nrows = 0;
129       for ( j=0; j<M; j++ ) {
130         if (rowhit[j]) {
131           c->rows[i][nrows]           = j;
132           c->columnsforrow[i][nrows] = rowhit[j] - 1;
133           nrows++;
134         }
135       }
136     } else {/*-------------------------------------------------------------------------------*/
137       /* efficient version, using rowhit as a linked list */
138       int currentcol,fm,mfm;
139       rowhit[M] = M;
140       nrows     = 0;
141       /* loop over columns*/
142       for ( j=0; j<nctot; j++ ) {
143         col  = cols[j];
144         if (col >= cstart && col < cend) {
145           /* column is in diagonal block of matrix */
146           rows = A_cj + A_ci[col-cstart];
147           m    = A_ci[col-cstart+1] - A_ci[col-cstart];
148         } else {
149           colb = aij->colmap[col] - 1;
150           if (colb == -1) {
151             m = 0;
152           } else {
153             rows = B_cj + B_ci[colb];
154             m    = B_ci[colb+1] - B_ci[colb];
155           }
156         }
157         /* loop over columns marking them in rowhit */
158         fm    = M; /* fm points to first entry in linked list */
159         for ( k=0; k<m; k++ ) {
160           currentcol = *rows++;
161 	  /* is it already in the list? */
162           do {
163             mfm  = fm;
164             fm   = rowhit[fm];
165           } while (fm < currentcol);
166           /* not in list so add it */
167           if (fm != currentcol) {
168             nrows++;
169             columnsforrow[currentcol] = col;
170             /* next three lines insert new entry into linked list */
171             rowhit[mfm]               = currentcol;
172             rowhit[currentcol]        = fm;
173             fm                        = currentcol;
174             /* fm points to present position in list since we know the columns are sorted */
175           } else {
176             SETERRQ(1,"MatFDColoringCreate_MPIAIJ:Invalid coloring");
177           }
178         }
179       }
180       c->nrows[i]         = nrows;
181       c->rows[i]          = (int *)PetscMalloc((nrows+1)*sizeof(int));CHKPTRQ(c->rows[i]);
182       c->columnsforrow[i] = (int *)PetscMalloc((nrows+1)*sizeof(int));CHKPTRQ(c->columnsforrow[i]);
183       /* now store the linked list of rows into c->rows[i] */
184       nrows = 0;
185       fm    = rowhit[M];
186       do {
187         c->rows[i][nrows]            = fm;
188         c->columnsforrow[i][nrows++] = columnsforrow[fm];
189         fm                           = rowhit[fm];
190       } while (fm < M);
191     } /* ---------------------------------------------------------------------------------------*/
192     PetscFree(cols);
193   }
194   PetscFree(rowhit);
195   PetscFree(columnsforrow);
196   PetscFree(ncolsonproc);
197   ierr = MatRestoreColumnIJ_SeqAIJ(aij->A,0,PETSC_FALSE,&ncols,&A_ci,&A_cj,&done); CHKERRQ(ierr);
198   ierr = MatRestoreColumnIJ_SeqAIJ(aij->B,0,PETSC_FALSE,&ncols,&B_ci,&B_cj,&done); CHKERRQ(ierr);
199 
200   c->scale  = (Scalar *) PetscMalloc( 2*mat->N*sizeof(Scalar) ); CHKPTRQ(c->scale);
201   c->wscale = c->scale + mat->N;
202   return 0;
203 }
204 
205