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